From c9165ea145bc7d866741a7701c99551ff7e33728 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Wed, 29 Jan 2020 21:32:02 +0100 Subject: [PATCH] idp_oidc: add "do not ask again" authorization checkbox (#22417) --- .../authentic2_idp_oidc/authorization.html | 5 +++- src/authentic2_idp_oidc/views.py | 28 +++++++++-------- tests/test_idp_oidc.py | 30 +++++++++++-------- 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/src/authentic2_idp_oidc/templates/authentic2_idp_oidc/authorization.html b/src/authentic2_idp_oidc/templates/authentic2_idp_oidc/authorization.html index 9c82cbdd..6be53e29 100644 --- a/src/authentic2_idp_oidc/templates/authentic2_idp_oidc/authorization.html +++ b/src/authentic2_idp_oidc/templates/authentic2_idp_oidc/authorization.html @@ -1,7 +1,7 @@ {% extends "authentic2/base-page.html" %} {% load i18n %} {% block content %} -
+

{% blocktrans with client_name=client.name %}Do you want to be authenticated on service {{ client_name }} ?{% endblocktrans %}

{% if scopes %}

{% trans "The following informations will be sent to the service:" %}

@@ -16,6 +16,9 @@ {% endif %} {% csrf_token %} +

+ +

diff --git a/src/authentic2_idp_oidc/views.py b/src/authentic2_idp_oidc/views.py index 3bcf7f65..bf35578e 100644 --- a/src/authentic2_idp_oidc/views.py +++ b/src/authentic2_idp_oidc/views.py @@ -270,18 +270,22 @@ def authorize(request, *args, **kwargs): fragment=fragment) if request.method == 'POST': if 'accept' in request.POST: - pk_to_deletes = [] - for authorization in qs: - # clean obsolete authorizations - if authorization.scope_set() <= scopes: - pk_to_deletes.append(authorization.pk) - auth_manager.create( - user=request.user, scopes=u' '.join(sorted(scopes)), - expired=start + datetime.timedelta(days=365)) - if pk_to_deletes: - auth_manager.filter(pk__in=pk_to_deletes).delete() - logger.info(u'authorized scopes %s for service %s', ' '.join(scopes), - client.name) + if 'do_not_ask_again' in request.POST: + pk_to_deletes = [] + for authorization in qs: + # clean obsolete authorizations + if authorization.scope_set() <= scopes: + pk_to_deletes.append(authorization.pk) + auth_manager.create( + user=request.user, scopes=u' '.join(sorted(scopes)), + expired=start + datetime.timedelta(days=365)) + if pk_to_deletes: + auth_manager.filter(pk__in=pk_to_deletes).delete() + logger.info(u'authorized scopes %s saved for service %s', ' '.join(scopes), + client.name) + else: + logger.info(u'authorized scopes %s for service %s', ' '.join(scopes), + client.name) else: logger.info(u'refused scopes %s for service %s', ' '.join(scopes), client.name) diff --git a/tests/test_idp_oidc.py b/tests/test_idp_oidc.py index 577c2e9e..b5685405 100644 --- a/tests/test_idp_oidc.py +++ b/tests/test_idp_oidc.py @@ -31,23 +31,20 @@ from django.core.files import File from django.db import connection from django.db.migrations.executor import MigrationExecutor from django.utils.timezone import now -from django.test.client import RequestFactory from django.contrib.auth import get_user_model from django.utils.six.moves.urllib import parse as urlparse -from ratelimit.utils import is_ratelimited -User = get_user_model() - from authentic2.models import Attribute, AuthorizedRole from authentic2_idp_oidc.models import OIDCClient, OIDCAuthorization, OIDCCode, OIDCAccessToken, OIDCClaim -from authentic2_idp_oidc.utils import (make_sub, get_first_rsa_sig_key, - base64url) +from authentic2_idp_oidc.utils import make_sub, get_first_rsa_sig_key, base64url from authentic2.a2_rbac.utils import get_default_ou from authentic2.utils import make_url from authentic2_auth_oidc.utils import parse_timestamp from django_rbac.utils import get_role_model +User = get_user_model() + pytestmark = pytest.mark.django_db JWKSET = { @@ -174,8 +171,9 @@ def bearer_authentication_headers(access_token): return {'Authorization': 'Bearer %s' % str(access_token)} +@pytest.mark.parametrize('do_not_ask_again', [(True,), (False,)]) @pytest.mark.parametrize('login_first', [(True,), (False,)]) -def test_authorization_code_sso(login_first, oidc_settings, oidc_client, simple_user, app): +def test_authorization_code_sso(login_first, do_not_ask_again, oidc_settings, oidc_client, simple_user, app): redirect_uri = oidc_client.redirect_uris.split()[0] params = { 'client_id': oidc_client.client_id, @@ -207,13 +205,17 @@ def test_authorization_code_sso(login_first, oidc_settings, oidc_client, simple_ assert OIDCAuthorization.objects.count() == 0 assert OIDCCode.objects.count() == 0 assert OIDCAccessToken.objects.count() == 0 + response.form['do_not_ask_again'] = do_not_ask_again response = response.form.submit('accept') - assert OIDCAuthorization.objects.count() == 1 - authz = OIDCAuthorization.objects.get() - assert authz.client == oidc_client - assert authz.user == simple_user - assert authz.scope_set() == set('openid profile email'.split()) - assert authz.expired >= now() + if do_not_ask_again: + assert OIDCAuthorization.objects.count() == 1 + authz = OIDCAuthorization.objects.get() + assert authz.client == oidc_client + assert authz.user == simple_user + assert authz.scope_set() == set('openid profile email'.split()) + assert authz.expired >= now() + else: + assert OIDCAuthorization.objects.count() == 0 if oidc_client.authorization_flow == oidc_client.FLOW_AUTHORIZATION_CODE: assert OIDCCode.objects.count() == 1 code = OIDCCode.objects.get() @@ -645,6 +647,7 @@ def test_invalid_request(caplog, oidc_settings, oidc_client, simple_user, app): authorize.scopes = 'openid profile' authorize.save() assert OIDCAuthorization.objects.count() == 1 + response.form['do_not_ask_again'] = True response = response.form.submit('accept') assert OIDCAuthorization.objects.count() == 1 # old authorizations have been deleted @@ -845,6 +848,7 @@ def test_role_control_access(login_first, oidc_settings, oidc_client, simple_use response = response.form.submit(name='login-password-submit') response = response.follow() if oidc_client.authorization_mode != oidc_client.AUTHORIZATION_MODE_NONE: + response.form['do_not_ask_again'] = True response = response.form.submit('accept') assert OIDCAuthorization.objects.get() if oidc_client.authorization_flow == oidc_client.FLOW_AUTHORIZATION_CODE: -- 2.24.0