Projet

Général

Profil

0001-idp_oidc-add-do-not-ask-again-authorization-checkbox.patch

Benjamin Dauvergne, 05 février 2020 10:22

Télécharger (7,77 ko)

Voir les différences:

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(-)
src/authentic2_idp_oidc/templates/authentic2_idp_oidc/authorization.html
1 1
{% extends "authentic2/base-page.html" %}
2 2
{% load i18n %}
3 3
{% block content %}
4
  <form method="post" id="a2-oidc-authorization-form">
4
<form method="post" id="a2-oidc-authorization-form">
5 5
    <p>{% blocktrans with client_name=client.name %}Do you want to be authenticated on service {{ client_name }} ?{% endblocktrans %}</p>
6 6
    {% if scopes %}
7 7
      <p>{% trans "The following informations will be sent to the service:" %}</p>
......
16 16
      </ul>
17 17
    {% endif %}
18 18
    {% csrf_token %}
19
    <p class="a2-oidc-authorization-form--do-not-ask-again">
20
      <label for="id_do_not_ask_again"><input type="checkbox" name="do_not_ask_again" value="on"/><span>{% trans "Do not ask again" %}</span></label>
21
    </p>
19 22
    <button name="accept">{% trans "Accept" %}</button>
20 23
    <button name="refuse">{% trans "Refuse" %}</button>
21 24
  </form>
src/authentic2_idp_oidc/views.py
270 270
                    fragment=fragment)
271 271
            if request.method == 'POST':
272 272
                if 'accept' in request.POST:
273
                    pk_to_deletes = []
274
                    for authorization in qs:
275
                        # clean obsolete authorizations
276
                        if authorization.scope_set() <= scopes:
277
                            pk_to_deletes.append(authorization.pk)
278
                    auth_manager.create(
279
                        user=request.user, scopes=u' '.join(sorted(scopes)),
280
                        expired=start + datetime.timedelta(days=365))
281
                    if pk_to_deletes:
282
                        auth_manager.filter(pk__in=pk_to_deletes).delete()
283
                    logger.info(u'authorized scopes %s for service %s', ' '.join(scopes),
284
                                client.name)
273
                    if 'do_not_ask_again' in request.POST:
274
                        pk_to_deletes = []
275
                        for authorization in qs:
276
                            # clean obsolete authorizations
277
                            if authorization.scope_set() <= scopes:
278
                                pk_to_deletes.append(authorization.pk)
279
                        auth_manager.create(
280
                            user=request.user, scopes=u' '.join(sorted(scopes)),
281
                            expired=start + datetime.timedelta(days=365))
282
                        if pk_to_deletes:
283
                            auth_manager.filter(pk__in=pk_to_deletes).delete()
284
                        logger.info(u'authorized scopes %s saved for service %s', ' '.join(scopes),
285
                                    client.name)
286
                    else:
287
                        logger.info(u'authorized scopes %s for service %s', ' '.join(scopes),
288
                                    client.name)
285 289
                else:
286 290
                    logger.info(u'refused scopes %s for service %s', ' '.join(scopes),
287 291
                                client.name)
tests/test_idp_oidc.py
31 31
from django.db import connection
32 32
from django.db.migrations.executor import MigrationExecutor
33 33
from django.utils.timezone import now
34
from django.test.client import RequestFactory
35 34
from django.contrib.auth import get_user_model
36 35
from django.utils.six.moves.urllib import parse as urlparse
37
from ratelimit.utils import is_ratelimited
38 36

  
39 37

  
40
User = get_user_model()
41

  
42 38
from authentic2.models import Attribute, AuthorizedRole
43 39
from authentic2_idp_oidc.models import OIDCClient, OIDCAuthorization, OIDCCode, OIDCAccessToken, OIDCClaim
44
from authentic2_idp_oidc.utils import (make_sub, get_first_rsa_sig_key,
45
        base64url)
40
from authentic2_idp_oidc.utils import make_sub, get_first_rsa_sig_key, base64url
46 41
from authentic2.a2_rbac.utils import get_default_ou
47 42
from authentic2.utils import make_url
48 43
from authentic2_auth_oidc.utils import parse_timestamp
49 44
from django_rbac.utils import get_role_model
50 45

  
46
User = get_user_model()
47

  
51 48
pytestmark = pytest.mark.django_db
52 49

  
53 50
JWKSET = {
......
174 171
    return {'Authorization': 'Bearer %s' % str(access_token)}
175 172

  
176 173

  
174
@pytest.mark.parametrize('do_not_ask_again', [(True,), (False,)])
177 175
@pytest.mark.parametrize('login_first', [(True,), (False,)])
178
def test_authorization_code_sso(login_first, oidc_settings, oidc_client, simple_user, app):
176
def test_authorization_code_sso(login_first, do_not_ask_again, oidc_settings, oidc_client, simple_user, app):
179 177
    redirect_uri = oidc_client.redirect_uris.split()[0]
180 178
    params = {
181 179
        'client_id': oidc_client.client_id,
......
207 205
        assert OIDCAuthorization.objects.count() == 0
208 206
        assert OIDCCode.objects.count() == 0
209 207
        assert OIDCAccessToken.objects.count() == 0
208
        response.form['do_not_ask_again'] = do_not_ask_again
210 209
        response = response.form.submit('accept')
211
        assert OIDCAuthorization.objects.count() == 1
212
        authz = OIDCAuthorization.objects.get()
213
        assert authz.client == oidc_client
214
        assert authz.user == simple_user
215
        assert authz.scope_set() == set('openid profile email'.split())
216
        assert authz.expired >= now()
210
        if do_not_ask_again:
211
            assert OIDCAuthorization.objects.count() == 1
212
            authz = OIDCAuthorization.objects.get()
213
            assert authz.client == oidc_client
214
            assert authz.user == simple_user
215
            assert authz.scope_set() == set('openid profile email'.split())
216
            assert authz.expired >= now()
217
        else:
218
            assert OIDCAuthorization.objects.count() == 0
217 219
    if oidc_client.authorization_flow == oidc_client.FLOW_AUTHORIZATION_CODE:
218 220
        assert OIDCCode.objects.count() == 1
219 221
        code = OIDCCode.objects.get()
......
645 647
    authorize.scopes = 'openid profile'
646 648
    authorize.save()
647 649
    assert OIDCAuthorization.objects.count() == 1
650
    response.form['do_not_ask_again'] = True
648 651
    response = response.form.submit('accept')
649 652
    assert OIDCAuthorization.objects.count() == 1
650 653
    # old authorizations have been deleted
......
845 848
        response = response.form.submit(name='login-password-submit')
846 849
        response = response.follow()
847 850
    if oidc_client.authorization_mode != oidc_client.AUTHORIZATION_MODE_NONE:
851
        response.form['do_not_ask_again'] = True
848 852
        response = response.form.submit('accept')
849 853
        assert OIDCAuthorization.objects.get()
850 854
    if oidc_client.authorization_flow == oidc_client.FLOW_AUTHORIZATION_CODE:
851
-