Projet

Général

Profil

0001-apps-hide-password-management-link-when-FC-authentic.patch

Benjamin Dauvergne, 03 mai 2019 16:48

Télécharger (6,12 ko)

Voir les différences:

Subject: [PATCH 1/2] apps: hide password management link when FC authenticated
 (#27083)

It's done by implementing a2_hook_user_can_change_password on the
AppConfig object.
 src/authentic2_auth_fc/__init__.py |   8 +++
 tests/test_auth_fc.py              | 103 +++++++++++++++++++++++++++++
 2 files changed, 111 insertions(+)
src/authentic2_auth_fc/__init__.py
1 1
from . import utils
2 2
from . import app_settings
3 3

  
4
from authentic2.utils import get_authentication_events
5

  
4 6
import django.apps
5 7

  
6 8

  
......
71 73
            return True
72 74
        return None
73 75

  
76
    def a2_hook_user_can_change_password(self, user, request, **kwargs):
77
        for authentication_event in get_authentication_events(request=request):
78
            if authentication_event['how'] == 'france-connect':
79
                return False
80
        return True
81

  
74 82

  
75 83
default_app_config = '%s.%s' % (__name__, 'AppConfig')
tests/test_auth_fc.py
456 456
    assert app.session['fc_states'][state]['next'] == '/accounts/'
457 457
    response = app.get(reverse('fc-logout') + '?state=' + state)
458 458
    assert path(response['Location']) == '/accounts/'
459

  
460

  
461
def test_can_change_password(app, fc_settings, caplog, hooks):
462
    exp = timestamp_from_datetime(now() + datetime.timedelta(seconds=1000))
463
    response = app.get('/login/?service=portail&next=/idp/')
464
    response = response.click("Register")
465
    response = response.click(href='callback')
466
    # 1. Try a login
467
    # 2. Verify we come back to login page
468
    # 3. Check presence of registration link
469
    # 4. Follow it
470
    location = response['Location']
471
    state = check_authorization_url(location)
472

  
473
    @httmock.urlmatch(path=r'.*/token$')
474
    def access_token_response(url, request):
475
        parsed = {x: y[0] for x, y in urlparse.parse_qs(request.body).items()}
476
        assert set(parsed.keys()) == set(['code', 'client_id', 'client_secret', 'redirect_uri',
477
                                          'grant_type'])
478
        assert parsed['code'] == 'zzz'
479
        assert parsed['client_id'] == 'xxx'
480
        assert parsed['client_secret'] == 'yyy'
481
        assert parsed['grant_type'] == 'authorization_code'
482
        assert callback in parsed['redirect_uri']
483
        id_token = {
484
            'sub': '1234',
485
            'aud': 'xxx',
486
            'nonce': state,
487
            'exp': exp,
488
            'iss': 'https://fcp.integ01.dev-franceconnect.fr/',
489
            'email': 'john.doe@example.com',
490
        }
491
        return json.dumps({
492
            'access_token': 'uuu',
493
            'id_token': hmac_jwt(id_token, 'yyy')
494
        })
495

  
496
    @httmock.urlmatch(path=r'.*userinfo$')
497
    def user_info_response(url, request):
498
        assert request.headers['Authorization'] == 'Bearer uuu'
499
        return json.dumps({
500
            'sub': '1234',
501
            'family_name': u'Frédérique',
502
            'given_name': u'Ÿuñe',
503
            'email': 'john.doe@example.com',
504
        })
505

  
506
    callback = urlparse.parse_qs(urlparse.urlparse(location).query)['redirect_uri'][0]
507
    with httmock.HTTMock(access_token_response, user_info_response):
508
        response = app.get(callback + '&code=zzz&state=%s' % state, status=302)
509
    assert User.objects.count() == 0
510
    assert path(response['Location']) == '/accounts/fc/register/'
511
    response = response.follow()
512
    location = response['Location']
513
    location.startswith('http://testserver/accounts/activate/')
514
    response = response.follow()
515
    assert hooks.calls['event'][0]['kwargs']['service'] == 'portail'
516
    assert hooks.calls['event'][1]['kwargs']['service'] == 'portail'
517
    # we must be connected
518
    assert app.session['_auth_user_id']
519
    # remove the registration parameter
520
    callback = callback.replace('&registration=', '')
521
    callback = callback.replace('?registration=', '?')
522
    callback = callback.replace('?&', '?')
523
    assert path_and_query(response['Location']) == path_and_query(callback)
524
    response = response.follow()
525
    location = response['Location']
526
    state = check_authorization_url(location)
527
    with httmock.HTTMock(access_token_response, user_info_response):
528
        response = app.get(callback + '&code=zzz&state=%s' % state, status=302)
529
    assert models.FcAccount.objects.count() == 1
530
    user = User.objects.get()
531
    assert user.verified_attributes.first_name == u'Ÿuñe'
532
    assert user.verified_attributes.last_name == u'Frédérique'
533
    response = app.get('/accounts/')
534
    assert len(response.pyquery('[href*="password/change"]')) == 0
535

  
536
    # Login with password
537
    user = User.objects.get()
538
    user.set_password('test')
539
    user.save()
540
    app.session.flush()
541
    response = app.get('/login/')
542
    response.form.set('username', User.objects.get().email)
543
    response.form.set('password', 'test')
544
    response = response.form.submit(name='login-password-submit').follow()
545
    response = app.get('/accounts/')
546
    assert len(response.pyquery('[href*="password/change"]')) > 0
547

  
548
    # Relogin with FC
549
    app.session.flush()
550
    response = app.get('/login/?service=portail&next=/accounts/')
551
    response = response.click(href='callback')
552
    location = response['Location']
553
    state = check_authorization_url(location)
554
    callback = urlparse.parse_qs(urlparse.urlparse(location).query)['redirect_uri'][0]
555
    with httmock.HTTMock(access_token_response, user_info_response):
556
        response = app.get(callback + '&code=zzz&state=%s' % state, status=302)
557
    # we must be connected
558
    assert app.session['_auth_user_id']
559
    assert path(response['Location']) == '/accounts/'
560
    response = response.follow()
561
    assert len(response.pyquery('[href*="password/change"]')) == 0
459
-