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('®istration=', '')
|
|
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 |
|
-
|