From f0c4132da4412cc9b455d326c2b613fba5a34cb9 Mon Sep 17 00:00:00 2001 From: Son NK Date: Sat, 10 Aug 2019 17:34:27 +0200 Subject: [PATCH] test id_token,token flow --- tests/oauth/test_authorize.py | 91 ++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/tests/oauth/test_authorize.py b/tests/oauth/test_authorize.py index 7c591f37..cee821cf 100644 --- a/tests/oauth/test_authorize.py +++ b/tests/oauth/test_authorize.py @@ -1,10 +1,11 @@ import base64 +import json from urllib.parse import urlparse, parse_qs from flask import url_for from app.extensions import db -from app.jose_utils import verify_id_token +from app.jose_utils import verify_id_token, decode_id_token from app.models import Client, User from app.oauth.views.authorize import ( get_host_name_and_scheme, @@ -387,3 +388,91 @@ def test_authorize_id_token_flow(flask_client): # id_token must be a valid, correctly signed JWT assert verify_id_token(queries["id_token"][0]) + + +def test_authorize_token_id_token_flow(flask_client): + """make sure the authorize redirects user to correct page for the *ID-Token Token Flow* + , ie when response_type=id_token,token + The /authorize endpoint should return an id_token and access_token + id_token, once decoded, should contain *at_hash* in payload + """ + + user = login(flask_client) + client = Client.create_new("test client", user.id) + + db.session.commit() + + # user allows client on the authorization page + r = flask_client.post( + url_for( + "oauth.authorize", + client_id=client.oauth_client_id, + state="teststate", + redirect_uri="http://localhost", + response_type="id_token token", # id_token,token flow + ), + data={"button": "allow", "suggested-email": "x@y.z", "suggested-name": "AB CD"}, + # user will be redirected to client page, do not allow redirection here + # to assert the redirect url + # follow_redirects=True, + ) + + assert r.status_code == 302 # user gets redirected back to client page + + # r.location will have this form http://localhost?state=teststate&code=knuyjepwvg + o = urlparse(r.location) + assert o.netloc == "localhost" + assert o.fragment + assert not o.query + + # parse the fragment, should return something like + # {'state': ['teststate'], 'id_token': ['knuyjepwvg']} + queries = parse_qs(o.fragment) + assert len(queries) == 3 + + assert queries["state"] == ["teststate"] + + # access_token must be returned + assert len(queries["id_token"]) == 1 + assert len(queries["access_token"]) == 1 + + # id_token must be a valid, correctly signed JWT + id_token = queries["id_token"][0] + assert verify_id_token(id_token) + + # make sure jwt has all the necessary fields + jwt = decode_id_token(id_token) + + # payload should have this format + # { + # 'at_hash': 'jLDmoGpuOIHwxeyFEe9SKw', + # 'aud': 'testclient-sywcpwsyua', + # 'auth_time': 1565450736, + # 'avatar_url': None, + # 'client': 'test client', + # 'email': 'x@y.z', + # 'email_verified': True, + # 'exp': 1565454336, + # 'iat': 1565450736, + # 'id': 1, + # 'iss': 'http://localhost', + # 'name': 'AB CD', + # 'sub': '1' + # } + payload = json.loads(jwt.claims) + + # at_hash MUST be present when the flow is id_token,token + assert "at_hash" in payload + + assert "aud" in payload + assert "auth_time" in payload + assert "avatar_url" in payload + assert "client" in payload + assert "email" in payload + assert "email_verified" in payload + assert "exp" in payload + assert "iat" in payload + assert "id" in payload + assert "iss" in payload + assert "name" in payload + assert "sub" in payload