Projet

Général

Profil

0002-idp_oidc-discard-profile-selection-from-do-not-ask-a.patch

Paul Marillonnet, 12 avril 2022 13:42

Télécharger (6,21 ko)

Voir les différences:

Subject: [PATCH 2/2] idp_oidc: discard profile selection from 'do not ask
 again' logic (#62889)

 .../authentic2_idp_oidc/authorization.html    | 13 ++++--
 src/authentic2_idp_oidc/views.py              |  9 +---
 tests/idp_oidc/test_user_profiles.py          | 45 ++++++++++++++++++-
 3 files changed, 54 insertions(+), 13 deletions(-)
src/authentic2_idp_oidc/templates/authentic2_idp_oidc/authorization.html
35 35
          <label for="{{ profile.id }}">
36 36
          {% with identifier=profile.identifier type_name=profile.profile_type.name %}
37 37
            {% trans "Unknown entity" as fallback_identifier %}
38
            <div>
38 39
            {% blocktrans %}Profile of type {{ type_name }}: {% endblocktrans %}
39
            {% firstof identifier fallback_identifier %}<br />
40
            {% firstof identifier fallback_identifier %}
41
            </div>
40 42
          {% endwith %}
41 43
          {% if profile.email %}
42
            {% blocktrans with email=profile.email %}Email address: {{ email }}{% endblocktrans %}<br />
44
            <div>
45
            {% blocktrans with email=profile.email %}Email address: {{ email }}{% endblocktrans %}
46
            </div>
43 47
          {% endif %}</label>
44 48
        </div>
45 49
      {% endfor %}
46 50
     </div>
47
    {% endif %}
48
    {% csrf_token %}
51
    {% else %}
49 52
    <p class="a2-oidc-authorization-form--do-not-ask-again">
50 53
      <label for="id_do_not_ask_again"><input id="id_do_not_ask_again" type="checkbox" name="do_not_ask_again" value="on"/><span>{% trans "Do not ask again" %}</span></label>
51 54
    </p>
55
    {% endif %}
56
    {% csrf_token %}
52 57
    <div class="buttons">
53 58
    <button name="accept">{% trans "Accept" %}</button>
54 59
    <button name="refuse">{% trans "Refuse" %}</button>
src/authentic2_idp_oidc/views.py
384 384
        else:
385 385
            qs = qs.filter(expired__gte=iat)
386 386
        authorized_scopes = set()
387
        authorized_profile = None
388 387
        for authorization in qs:
389 388
            authorized_scopes |= authorization.scope_set()
390
            # load first authorized profile
391
            if not authorized_profile and authorization.profile:
392
                authorized_profile = authorization.profile
393
        if request.user.profiles.count() and not authorized_profile and client.activate_user_profiles:
389
        if request.user.profiles.count() and client.activate_user_profiles:
394 390
            needs_profile_validation = True
395
        else:
396
            profile = authorized_profile
397 391
        if (authorized_scopes & scopes) < scopes:
398 392
            needs_scope_validation = True
399 393
        if needs_scope_validation or needs_profile_validation:
......
417 411
                                pk_to_deletes.append(authorization.pk)
418 412
                        auth_manager.create(
419 413
                            user=request.user,
420
                            profile=profile,
421 414
                            scopes=' '.join(sorted(scopes)),
422 415
                            expired=iat + datetime.timedelta(days=365),
423 416
                        )
tests/idp_oidc/test_user_profiles.py
30 30

  
31 31
from authentic2.custom_user.models import Profile, ProfileType
32 32
from authentic2.utils.misc import make_url
33
from authentic2_idp_oidc.models import OIDCAccessToken, OIDCCode
33
from authentic2_idp_oidc.models import OIDCAccessToken, OIDCAuthorization, OIDCCode
34 34
from authentic2_idp_oidc.utils import get_jwkset, make_pairwise_sub, make_sub, reverse_pairwise_sub
35 35

  
36 36
from .. import utils
......
428 428
    assert claims['email'] == 'def@ad.dre.ss'
429 429
    assert claims['profile'] == profile_user.profiles.first().id
430 430
    assert claims['customclaim'] == 'whatever'
431

  
432

  
433
def test_do_no_ask_again(app, oidc_client, profile_user, profile_settings):
434
    oidc_client.idtoken_algo = oidc_client.ALGO_HMAC
435
    oidc_client.activate_user_profiles = True
436
    oidc_client.perform_sub_profile_substitution = True
437
    oidc_client.save()
438
    redirect_uri = oidc_client.redirect_uris.split()[0]
439
    params = {
440
        'client_id': oidc_client.client_id,
441
        'scope': 'openid profile email',
442
        'redirect_uri': redirect_uri,
443
        'state': 'xxx',
444
        'nonce': 'yyy',
445
        'login_hint': 'backoffice john@example.com',
446
        'response_type': 'code',
447
    }
448

  
449
    authorize_url = make_url('oidc-authorize', params=params)
450
    utils.login(app, profile_user)
451

  
452
    # attempt with profile, 'do not ask again' checkbox absent
453
    response = app.get(authorize_url)
454
    assert 'do_not_ask_again' not in response.text
455

  
456
    # when no profile is set, fallback to usual 'do not ask again' logic
457
    Profile.objects.filter(user=profile_user).delete()
458
    response = app.get(authorize_url)
459
    assert 'do_not_ask_again' in response.text
460
    assert OIDCAuthorization.objects.filter(user=profile_user).count() == 0
461
    response.form['do_not_ask_again'] = True
462
    response.form.submit('accept')
463

  
464
    # when an authorization has been defined yet the user posesses profiles,
465
    # the authorization form is still displayed
466
    assert OIDCAuthorization.objects.filter(user=profile_user).count() == 1
467
    Profile.objects.create(
468
        user=profile_user,
469
        profile_type=ProfileType.objects.first(),
470
        email='entity123@example.org',
471
    )
472
    response = app.get(authorize_url)
473
    assert 'do_not_ask_again' not in response.text
431
-