Projet

Général

Profil

0002-views-allow-adapter-to-force-authentication-55953.patch

Benjamin Dauvergne, 03 août 2021 16:46

Télécharger (6,21 ko)

Voir les différences:

Subject: [PATCH 2/2] views: allow adapter to force authentication (#55953)

 mellon/utils.py       |  8 ++++++++
 mellon/views.py       |  3 +--
 tests/__init__.py     |  0
 tests/adapters.py     | 19 +++++++++++++++++++
 tests/test_sso_slo.py | 20 +++++++++++++++++---
 tests/test_utils.py   |  2 +-
 tests/test_views.py   |  4 ++--
 testsettings.py       |  2 +-
 8 files changed, 49 insertions(+), 9 deletions(-)
 create mode 100644 tests/__init__.py
 create mode 100644 tests/adapters.py
mellon/utils.py
282 282
        auth.login(request, user)
283 283

  
284 284

  
285
def should_force_authn(request):
286
    result = False
287
    for adapter in get_adapters():
288
        if hasattr(adapter, 'should_force_authn'):
289
            result |= adapter.should_force_authn(request)
290
    return result
291

  
292

  
285 293
def get_xml_encoding(content):
286 294
    xml_encoding = 'utf-8'
287 295

  
mellon/views.py
501 501
            # link the nonce to the request-id
502 502
            if 'nonce' in request.GET:
503 503
                self.set_nonce(request.GET['nonce'][:128])
504
            if force_authn:
505
                authn_request.forceAuthn = True
504
            authn_request.forceAuthn = force_authn or utils.should_force_authn(request)
506 505
            if request.GET.get('passive') == '1':
507 506
                authn_request.isPassive = True
508 507
            # configure requested AuthnClassRef
tests/adapters.py
1
# django-mellon - SAML2 authentication for Django
2
# Copyright (C) 2014-2021 Entr'ouvert
3
# This program is free software: you can redistribute it and/or modify
4
# it under the terms of the GNU Affero General Public License as
5
# published by the Free Software Foundation, either version 3 of the
6
# License, or (at your option) any later version.
7

  
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU Affero General Public License for more details.
12

  
13
# You should have received a copy of the GNU Affero General Public License
14
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
15

  
16

  
17
class ShouldForceAuthnAdapter:
18
    def should_force_authn(self, request):
19
        return True
tests/test_sso_slo.py
94 94
        self.session_dump = None
95 95

  
96 96
    def process_authn_request_redirect(self, url, auth_result=True, consent=True, msg=None):
97
        login = lasso.Login(self.server)
97
        login = self.login = lasso.Login(self.server)
98 98
        if self.identity_dump:
99 99
            login.setIdentityFromDump(self.identity_dump)
100 100
        if self.session_dump:
......
445 445
        )
446 446

  
447 447

  
448
@pytest.mark.urls('urls_tests_template_base')
448
@pytest.mark.urls('tests.urls_tests_template_base')
449 449
def test_template_base(db, app, idp, caplog, sp_settings):
450 450
    response = app.get(reverse('mellon_metadata'))
451 451
    response = app.get(reverse('mellon_login'))
......
462 462
    assert urlparse.urlparse(response['Location']).path == '/singleLogout'
463 463

  
464 464

  
465
@pytest.mark.urls('urls_tests_template_hook')
465
@pytest.mark.urls('tests.urls_tests_template_hook')
466 466
def test_template_hook(db, app, idp, caplog, sp_settings):
467 467
    response = app.get(reverse('mellon_metadata'))
468 468
    response = app.get(reverse('mellon_login'))
......
739 739
    url, body, relay_state = idp.process_authn_request_redirect(response['Location'])
740 740
    response = app.post(reverse('mellon_login'), params={'SAMLResponse': body, 'RelayState': relay_state})
741 741
    assert app.session['mellon_session']['nonce'] == '1234'
742

  
743

  
744
def test_adapter_should_force_authn(db, app, idp, caplog, sp_settings):
745
    response = app.get(reverse('mellon_login'))
746
    idp.process_authn_request_redirect(response['Location'])
747
    assert not idp.login.request.forceAuthn
748

  
749
    sp_settings.MELLON_ADAPTER = [
750
        'mellon.adapters.DefaultAdapter',
751
        'tests.adapters.ShouldForceAuthnAdapter',
752
    ]
753
    response = app.get(reverse('mellon_login'))
754
    idp.process_authn_request_redirect(response['Location'])
755
    assert idp.login.request.forceAuthn
tests/test_utils.py
22 22

  
23 23
from mellon.utils import create_metadata, iso8601_to_datetime, flatten_datetime
24 24
from mellon.views import check_next_url
25
from xml_utils import assert_xml_constraints
25
from .xml_utils import assert_xml_constraints
26 26

  
27 27

  
28 28
def test_create_metadata(rf, private_settings, caplog):
tests/test_views.py
27 27
from django.utils.encoding import force_text
28 28
from django.utils.http import urlencode
29 29

  
30
from xml_utils import assert_xml_constraints
30
from .xml_utils import assert_xml_constraints
31 31

  
32
from utils import error_500, html_response
32
from .utils import error_500, html_response
33 33

  
34 34
pytestmark = pytest.mark.django_db
35 35

  
testsettings.py
31 31
    )
32 32

  
33 33
AUTHENTICATION_BACKENDS = ('mellon.backends.SAMLBackend',)
34
ROOT_URLCONF = 'urls_tests'
34
ROOT_URLCONF = 'tests.urls_tests'
35 35
TEMPLATE_DIRS = [
36 36
    'tests/templates/',
37 37
]
38
-