diff --git a/CHANGELOG.md b/CHANGELOG.md index d0a80e1..c67d47a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file. ##### Fixed - CORS in discovery and userinfo endpoint. - Client type public bug when created using the admin. +- Missing OIDC_TOKEN_EXPIRE setting on implicit flow. ### [0.3.7] - 2016-08-31 diff --git a/oidc_provider/lib/endpoints/authorize.py b/oidc_provider/lib/endpoints/authorize.py index 54af1a7..f6161b5 100644 --- a/oidc_provider/lib/endpoints/authorize.py +++ b/oidc_provider/lib/endpoints/authorize.py @@ -151,6 +151,7 @@ class AuthorizeEndpoint(object): 'aud': self.client.client_id, 'nonce': self.params.nonce, 'request': self.request, + 'scope': self.params.scope, } # Include at_hash when access_token is being returned. if 'access_token' in query_fragment: diff --git a/oidc_provider/lib/endpoints/token.py b/oidc_provider/lib/endpoints/token.py index a10c508..77cd636 100644 --- a/oidc_provider/lib/endpoints/token.py +++ b/oidc_provider/lib/endpoints/token.py @@ -153,6 +153,7 @@ class TokenEndpoint(object): nonce=self.code.nonce, at_hash=token.at_hash, request=self.request, + scope=self.params.scope, ) else: id_token_dic = {} @@ -188,6 +189,7 @@ class TokenEndpoint(object): nonce=None, at_hash=token.at_hash, request=self.request, + scope=self.params.scope, ) else: id_token_dic = {} diff --git a/oidc_provider/lib/utils/token.py b/oidc_provider/lib/utils/token.py index 635feaf..f07ad34 100644 --- a/oidc_provider/lib/utils/token.py +++ b/oidc_provider/lib/utils/token.py @@ -17,7 +17,7 @@ from oidc_provider.models import ( from oidc_provider import settings -def create_id_token(user, aud, nonce, at_hash=None, request=None): +def create_id_token(user, aud, nonce, at_hash=None, request=None, scope=[]): """ Creates the id_token dictionary. See: http://openid.net/specs/openid-connect-core-1_0.html#IDToken @@ -50,7 +50,7 @@ def create_id_token(user, aud, nonce, at_hash=None, request=None): if at_hash: dic['at_hash'] = at_hash - if getattr(user, 'email', None): + if ('email' in scope) and getattr(user, 'email', None): dic['email'] = user.email processing_hook = settings.get('OIDC_IDTOKEN_PROCESSING_HOOK') diff --git a/oidc_provider/tests/test_authorize_endpoint.py b/oidc_provider/tests/test_authorize_endpoint.py index bd05163..030d50b 100644 --- a/oidc_provider/tests/test_authorize_endpoint.py +++ b/oidc_provider/tests/test_authorize_endpoint.py @@ -11,7 +11,10 @@ import uuid from django.contrib.auth.models import AnonymousUser from django.core.management import call_command from django.core.urlresolvers import reverse -from django.test import RequestFactory +from django.test import ( + RequestFactory, + override_settings, +) from django.test import TestCase from jwkest.jwt import JWT @@ -457,12 +460,8 @@ class AuthorizationHybridFlowTestCase(TestCase, AuthorizeEndpointMixin): self.state = uuid.uuid4().hex self.nonce = uuid.uuid4().hex - def test_code_idtoken_token_response(self): - """ - Implicit client requesting `id_token token` receives both id token - and access token as the result of the authorization request. - """ - data = { + # Base data for the auth request. + self.data = { 'client_id': self.client_code_idtoken_token.client_id, 'redirect_uri': self.client_code_idtoken_token.default_redirect_uri, 'response_type': self.client_code_idtoken_token.response_type, @@ -472,7 +471,12 @@ class AuthorizationHybridFlowTestCase(TestCase, AuthorizeEndpointMixin): 'allow': 'Accept', } - response = self._auth_request('post', data, is_user_authenticated=True) + def test_code_idtoken_token_response(self): + """ + Implicit client requesting `id_token token` receives both id token + and access token as the result of the authorization request. + """ + response = self._auth_request('post', self.data, is_user_authenticated=True) self.assertIn('#', response['Location']) self.assertIn('access_token', response['Location']) @@ -485,3 +489,12 @@ class AuthorizationHybridFlowTestCase(TestCase, AuthorizeEndpointMixin): user=self.user, client=self.client_code_idtoken_token) self.assertEqual(is_code_ok, True, msg='Code returned is invalid.') + + @override_settings(OIDC_TOKEN_EXPIRE=36000) + def test_access_token_expiration(self): + """ + Add ten hours of expiration to access_token. Check for the expires_in query in fragment. + """ + response = self._auth_request('post', self.data, is_user_authenticated=True) + + self.assertIn('expires_in=36000', response['Location']) diff --git a/oidc_provider/tests/test_token_endpoint.py b/oidc_provider/tests/test_token_endpoint.py index 7c43122..7f705d6 100644 --- a/oidc_provider/tests/test_token_endpoint.py +++ b/oidc_provider/tests/test_token_endpoint.py @@ -10,7 +10,10 @@ except ImportError: from django.core.management import call_command from django.core.urlresolvers import reverse -from django.test import RequestFactory, override_settings +from django.test import ( + RequestFactory, + override_settings, +) from django.test import TestCase from django.utils import timezone from jwkest.jwk import KEYS @@ -148,7 +151,7 @@ class TokenTestCase(TestCase): self.assertEqual(response_dic['token_type'], 'bearer') self.assertEqual(response_dic['expires_in'], 720) self.assertEqual(id_token['sub'], str(self.user.id)) - self.assertEqual(id_token['aud'], self.client.client_id) + self.assertEqual(id_token['aud'], self.client.client_id); def test_refresh_token(self): """ diff --git a/oidc_provider/tests/test_userinfo_endpoint.py b/oidc_provider/tests/test_userinfo_endpoint.py index 78dc8d4..de95cd8 100644 --- a/oidc_provider/tests/test_userinfo_endpoint.py +++ b/oidc_provider/tests/test_userinfo_endpoint.py @@ -34,14 +34,20 @@ class UserInfoTestCase(TestCase): """ Generate a valid token. """ - id_token_dic = create_id_token(self.user, - self.client.client_id, FAKE_NONCE) + scope = ['openid', 'email'] + extra_scope + + id_token_dic = create_id_token( + user=self.user, + aud=self.client.client_id, + nonce=FAKE_NONCE, + scope=scope, + ) token = create_token( user=self.user, client=self.client, id_token_dic=id_token_dic, - scope=['openid', 'email'] + extra_scope) + scope=scope) token.save() return token