0002-views-allow-adapter-to-force-authentication-55953.patch
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 |
- |