def test_parse_id_token_nonce_supported(self): key = jwk.dumps('secret', 'oct', kid='f') token = get_bearer_token() id_token = generate_id_token( token, {'sub': '123', 'nonce_supported': False}, key, alg='HS256', iss='https://i.b', aud='dev', exp=3600, ) app = Flask(__name__) app.secret_key = '!' oauth = OAuth(app) client = oauth.register( 'dev', client_id='dev', client_secret='dev', fetch_token=get_bearer_token, jwks={'keys': [key]}, issuer='https://i.b', id_token_signing_alg_values_supported=['HS256', 'RS256'], ) with app.test_request_context(): session['_dev_authlib_nonce_'] = 'n' token['id_token'] = id_token user = client.parse_id_token(token) self.assertEqual(user.sub, '123')
async def test_runtime_error_fetch_jwks_uri(): key = jwk.dumps('secret', 'oct', kid='f') token = get_bearer_token() id_token = generate_id_token( token, {'sub': '123'}, key, alg='HS256', iss='https://i.b', aud='dev', exp=3600, nonce='n', ) oauth = OAuth() client = oauth.register( 'dev', client_id='dev', client_secret='dev', fetch_token=get_bearer_token, issuer='https://i.b', id_token_signing_alg_values_supported=['HS256'], ) req_scope = {'type': 'http', 'session': {'_dev_authlib_nonce_': 'n'}} req = Request(req_scope) token['id_token'] = id_token with pytest.raises(RuntimeError): await client.parse_id_token(req, token)
def test_runtime_error_fetch_jwks_uri(self): key = jwk.dumps('secret', 'oct', kid='f') token = get_bearer_token() id_token = generate_id_token( token, {'sub': '123'}, key, alg='HS256', iss='https://i.b', aud='dev', exp=3600, nonce='n', ) app = Flask(__name__) app.secret_key = '!' oauth = OAuth(app) client = oauth.register( 'dev', client_id='dev', client_secret='dev', fetch_token=get_bearer_token, jwks={'keys': [jwk.dumps('secret', 'oct', kid='b')]}, issuer='https://i.b', id_token_signing_alg_values_supported=['HS256'], ) with app.test_request_context(): session['_dev_authlib_nonce_'] = 'n' token['id_token'] = id_token self.assertRaises(RuntimeError, client.parse_id_token, token)
async def test_force_fetch_jwks_uri(): secret_keys = read_file_path('jwks_private.json') token = get_bearer_token() id_token = generate_id_token( token, {'sub': '123'}, secret_keys, alg='RS256', iss='https://i.b', aud='dev', exp=3600, nonce='n', ) app = AsyncPathMapDispatch({ '/jwks': {'body': read_file_path('jwks_public.json')} }) oauth = OAuth() client = oauth.register( 'dev', client_id='dev', client_secret='dev', fetch_token=get_bearer_token, jwks_uri='https://i.b/jwks', issuer='https://i.b', client_kwargs={ 'app': app, } ) req_scope = {'type': 'http', 'session': {'_dev_authlib_nonce_': 'n'}} req = Request(req_scope) token['id_token'] = id_token user = await client.parse_id_token(req, token) assert user.sub == '123'
def test_openid_authorize(self): request = testing.DummyRequest(path="/login") key = jwk.dumps('secret', 'oct', kid='f') oauth = OAuth() client = oauth.register( 'dev', client_id='dev', jwks={'keys': [key]}, api_base_url='https://i.b/api', access_token_url='https://i.b/token', authorize_url='https://i.b/authorize', client_kwargs={'scope': 'openid profile'}, ) resp = client.authorize_redirect(request, 'https://b.com/bar') assert resp.status_code == 302 url = resp.headers.get('location') assert 'nonce=' in url query_data = dict(url_decode(urlparse.urlparse(url).query)) token = get_bearer_token() token['id_token'] = generate_id_token( token, {'sub': '123'}, key, alg='HS256', iss='https://i.b', aud='dev', exp=3600, nonce=query_data['nonce'], ) state = query_data['state'] metadata = { "issuer": "https://i.b", "id_token_signing_alg_values_supported": ["HS256", "RS256"], 'jwks': {'keys': [{'k': 'c2VjcmV0', 'kid': 'f', 'kty': 'oct'}]} } with ( mock.patch('requests.sessions.Session.send') as send, mock.patch.object(client, "load_server_metadata") as load_server_metadata ): send.return_value = mock_send_value(token) load_server_metadata.return_value = metadata request2 = testing.DummyRequest( path='/authorize', params={"state": state, "code": 'foo'}, ) request2.session = request.session token = client.authorize_access_token(request2) assert token['access_token'] == 'a' assert 'userinfo' in token assert token['userinfo']['sub'] == '123'
def __call__(self, client: Client, grant_type: str, user: UserWithRoles, scope: str): jwt_config = self.get_jwt_config() jwt_config['aud'] = [client.get_client_id()] jwt_config['auth_time'] = int(time.time()) user_info = {'sub': user.user.id, 'roles': user.roles} if 'groups' in scope_to_list(scope): user_info['groups'] = user.user.groups return generate_id_token({}, user_info, code=generate_token( config.oauth2.access_token_length), **jwt_config)
def test_openid_authorize(self): app = Flask(__name__) app.secret_key = '!' oauth = OAuth(app) key = jwk.dumps('secret', 'oct', kid='f') client = oauth.register( 'dev', client_id='dev', api_base_url='https://i.b/api', access_token_url='https://i.b/token', authorize_url='https://i.b/authorize', client_kwargs={'scope': 'openid profile'}, jwks={'keys': [key]}, ) with app.test_request_context(): resp = client.authorize_redirect('https://b.com/bar') self.assertEqual(resp.status_code, 302) url = resp.headers['Location'] query_data = dict(url_decode(urlparse.urlparse(url).query)) state = query_data['state'] self.assertIsNotNone(state) session_data = session[f'_state_dev_{state}'] nonce = session_data['data']['nonce'] self.assertIsNotNone(nonce) self.assertEqual(nonce, query_data['nonce']) token = get_bearer_token() token['id_token'] = generate_id_token( token, {'sub': '123'}, key, alg='HS256', iss='https://i.b', aud='dev', exp=3600, nonce=query_data['nonce'], ) path = '/?code=a&state={}'.format(state) with app.test_request_context(path=path): session[f'_state_dev_{state}'] = session_data with mock.patch('requests.sessions.Session.send') as send: send.return_value = mock_send_value(token) token = client.authorize_access_token() self.assertEqual(token['access_token'], 'a') self.assertIn('userinfo', token)
def test_openid_authorize(self): request = self.factory.get('/login') request.session = self.factory.session key = jwk.dumps('secret', 'oct', kid='f') oauth = OAuth() client = oauth.register( 'dev', client_id='dev', jwks={'keys': [key]}, api_base_url='https://i.b/api', access_token_url='https://i.b/token', authorize_url='https://i.b/authorize', client_kwargs={'scope': 'openid profile'}, ) resp = client.authorize_redirect(request, 'https://b.com/bar') self.assertEqual(resp.status_code, 302) url = resp.get('Location') self.assertIn('nonce=', url) query_data = dict(url_decode(urlparse.urlparse(url).query)) token = get_bearer_token() token['id_token'] = generate_id_token( token, {'sub': '123'}, key, alg='HS256', iss='https://i.b', aud='dev', exp=3600, nonce=query_data['nonce'], ) state = query_data['state'] with mock.patch('requests.sessions.Session.send') as send: send.return_value = mock_send_value(token) request2 = self.factory.get( '/authorize?state={}&code=foo'.format(state)) request2.session = request.session token = client.authorize_access_token(request2) self.assertEqual(token['access_token'], 'a') self.assertIn('userinfo', token) self.assertEqual(token['userinfo']['sub'], '123')
def _gen_token(nonce, domain): token = {"token_type": "Bearer", "access_token": "at", "expires_in": 3600} token["id_token"] = generate_id_token( token, { "email": f"matthew@{domain}", "name": "Matthew Smith", "given_name": "Matthew", "family_name": "Smith", "sub": "123", "hd": domain, }, key, alg="HS256", iss="iss", aud="cid", nonce=nonce, ) return token
def test_parse_id_token(self): key = jwk.dumps('secret', 'oct', kid='f') token = get_bearer_token() id_token = generate_id_token( token, {'sub': '123'}, key, alg='HS256', iss='https://i.b', aud='dev', exp=3600, nonce='n', ) app = Flask(__name__) app.secret_key = '!' oauth = OAuth(app) client = oauth.register( 'dev', client_id='dev', client_secret='dev', fetch_token=get_bearer_token, jwks={'keys': [key]}, issuer='https://i.b', id_token_signing_alg_values_supported=['HS256', 'RS256'], ) with app.test_request_context(): self.assertIsNone(client.parse_id_token(token, nonce='n')) token['id_token'] = id_token user = client.parse_id_token(token, nonce='n') self.assertEqual(user.sub, '123') claims_options = {'iss': {'value': 'https://i.b'}} user = client.parse_id_token(token, nonce='n', claims_options=claims_options) self.assertEqual(user.sub, '123') claims_options = {'iss': {'value': 'https://i.c'}} self.assertRaises(InvalidClaimError, client.parse_id_token, token, 'n', claims_options)
def test_force_fetch_jwks_uri(self): secret_keys = read_file_path('jwks_private.json') token = get_bearer_token() id_token = generate_id_token( token, {'sub': '123'}, secret_keys, alg='RS256', iss='https://i.b', aud='dev', exp=3600, nonce='n', ) app = Flask(__name__) app.secret_key = '!' oauth = OAuth(app) client = oauth.register( 'dev', client_id='dev', client_secret='dev', fetch_token=get_bearer_token, jwks={'keys': [jwk.dumps('secret', 'oct', kid='f')]}, jwks_uri='https://i.b/jwks', issuer='https://i.b', ) def fake_send(sess, req, **kwargs): resp = mock.MagicMock() resp.json = lambda: read_file_path('jwks_public.json') resp.status_code = 200 return resp with app.test_request_context(): session['_dev_authlib_nonce_'] = 'n' self.assertIsNone(client.parse_id_token(token)) with mock.patch('requests.sessions.Session.send', fake_send): token['id_token'] = id_token user = client.parse_id_token(token) self.assertEqual(user.sub, '123')
async def test_parse_id_token(): key = jwk.dumps('secret', 'oct', kid='f') token = get_bearer_token() id_token = generate_id_token( token, {'sub': '123'}, key, alg='HS256', iss='https://i.b', aud='dev', exp=3600, nonce='n', ) oauth = OAuth() client = oauth.register( 'dev', client_id='dev', client_secret='dev', fetch_token=get_bearer_token, jwks={'keys': [key]}, issuer='https://i.b', id_token_signing_alg_values_supported=['HS256', 'RS256'], ) req_scope = {'type': 'http', 'session': {'_dev_authlib_nonce_': 'n'}} req = Request(req_scope) user = await client.parse_id_token(req, token) assert user is None token['id_token'] = id_token user = await client.parse_id_token(req, token) assert user.sub == '123' claims_options = {'iss': {'value': 'https://i.b'}} user = await client.parse_id_token(req, token, claims_options) assert user.sub == '123' with pytest.raises(InvalidClaimError): claims_options = {'iss': {'value': 'https://i.c'}} await client.parse_id_token(req, token, claims_options)