Projet

Général

Profil

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

Paul Marillonnet, 17 mars 2022 14:06

Télécharger (6,22 ko)

Voir les différences:

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

 .../authentic2_idp_oidc/authorization.html    | 13 ++++--
 src/authentic2_idp_oidc/views.py              |  8 ----
 tests/idp_oidc/test_user_profiles.py          | 45 ++++++++++++++++++-
 3 files changed, 53 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
    <button name="accept">{% trans "Accept" %}</button>
53 58
    <button name="refuse">{% trans "Refuse" %}</button>
54 59
  </form>
src/authentic2_idp_oidc/views.py
383 383
        else:
384 384
            qs = qs.filter(expired__gte=iat)
385 385
        authorized_scopes = set()
386
        authorized_profile = None
387 386
        for authorization in qs:
388 387
            authorized_scopes |= authorization.scope_set()
389
            # load first authorized profile
390
            if not authorized_profile and authorization.profile:
391
                authorized_profile = authorization.profile
392 388
        if (
393 389
            request.user.profiles.count()
394
            and not authorized_profile
395 390
            and client.activate_user_profiles
396 391
            and a2_app_settings.A2_USER_PROFILE_MANAGEMENT
397 392
        ):
398 393
            needs_profile_validation = True
399
        else:
400
            profile = authorized_profile
401 394
        if (authorized_scopes & scopes) < scopes:
402 395
            needs_scope_validation = True
403 396
        if needs_scope_validation or needs_profile_validation:
......
421 414
                                pk_to_deletes.append(authorization.pk)
422 415
                        auth_manager.create(
423 416
                            user=request.user,
424
                            profile=profile,
425 417
                            scopes=' '.join(sorted(scopes)),
426 418
                            expired=iat + datetime.timedelta(days=365),
427 419
                        )
tests/idp_oidc/test_user_profiles.py
29 29

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

  
35 35
from .. import utils
......
380 380
        assert sub_with_profile != sub_without_profile
381 381
        assert uuid_with_profile == uuid_without_profile
382 382
        assert uuid_with_profile == UUID(user.uuid).bytes
383

  
384

  
385
def test_do_no_ask_again(app, oidc_client, profile_user, profile_settings):
386
    oidc_client.idtoken_algo = oidc_client.ALGO_HMAC
387
    oidc_client.activate_user_profiles = True
388
    oidc_client.perform_sub_profile_substitution = True
389
    oidc_client.save()
390
    redirect_uri = oidc_client.redirect_uris.split()[0]
391
    params = {
392
        'client_id': oidc_client.client_id,
393
        'scope': 'openid profile email',
394
        'redirect_uri': redirect_uri,
395
        'state': 'xxx',
396
        'nonce': 'yyy',
397
        'login_hint': 'backoffice john@example.com',
398
        'response_type': 'code',
399
    }
400

  
401
    authorize_url = make_url('oidc-authorize', params=params)
402
    utils.login(app, profile_user)
403

  
404
    # attempt with profile, 'do not ask again' checkbox absent
405
    response = app.get(authorize_url)
406
    assert 'do_not_ask_again' not in response.text
407

  
408
    # when no profile is set, fallback to usual 'do not ask again' logic
409
    Profile.objects.filter(user=profile_user).delete()
410
    response = app.get(authorize_url)
411
    assert 'do_not_ask_again' in response.text
412
    assert OIDCAuthorization.objects.filter(user=profile_user).count() == 0
413
    response.form['do_not_ask_again'] = True
414
    response.form.submit('accept')
415

  
416
    # when an authorization has been defined yet the user posesses profiles,
417
    # the authorization form is still displayed
418
    assert OIDCAuthorization.objects.filter(user=profile_user).count() == 1
419
    Profile.objects.create(
420
        user=profile_user,
421
        profile_type=ProfileType.objects.first(),
422
        email='entity123@example.org',
423
    )
424
    response = app.get(authorize_url)
425
    assert 'do_not_ask_again' not in response.text
383
-