def test_get_issuer(self): request = Request() # from default settings self.assertEqual(get_issuer(), 'http://localhost:8000/openid') # from custom settings with self.settings(SITE_URL='http://otherhost:8000'): self.assertEqual(get_issuer(), 'http://otherhost:8000/openid') # `SITE_URL` not set, from `request` with self.settings(SITE_URL=''): self.assertEqual(get_issuer(request=request), 'http://host-from-request:8888/openid') # use settings first if both are provided self.assertEqual(get_issuer(request=request), 'http://localhost:8000/openid') # `site_url` can even be overridden manually self.assertEqual(get_issuer(site_url='http://127.0.0.1:9000', request=request), 'http://127.0.0.1:9000/openid')
def create_response_dic(self): sub = settings.get('OIDC_IDTOKEN_SUB_GENERATOR')(user=self.code.user) id_token_dic = create_id_token(iss=get_issuer(), sub=sub, aud=self.client.client_id, auth_time=self.code.user.last_login) token = create_token(user=self.code.user, client=self.code.client, id_token_dic=id_token_dic, scope=self.code.scope) # Store the token. token.save() # We don't need to store the code anymore. self.code.delete() id_token = encode_id_token(id_token_dic, self.client.client_secret) dic = { 'access_token': token.access_token, 'token_type': 'bearer', 'expires_in': settings.get('OIDC_TOKEN_EXPIRE'), 'id_token': id_token, } return dic
def create_response_dic(self): sub = settings.get('OIDC_IDTOKEN_SUB_GENERATOR')( user=self.code.user) id_token_dic = create_id_token( iss=get_issuer(), sub=sub, aud=self.client.client_id, auth_time=self.code.user.last_login) token = create_token( user=self.code.user, client=self.code.client, id_token_dic=id_token_dic, scope=self.code.scope) # Store the token. token.save() # We don't need to store the code anymore. self.code.delete() id_token = encode_id_token(id_token_dic, self.client.client_secret) dic = { 'access_token': token.access_token, 'token_type': 'bearer', 'expires_in': settings.get('OIDC_TOKEN_EXPIRE'), 'id_token': id_token, } return dic
def get(self, request, *args, **kwargs): dic = dict() dic['issuer'] = get_issuer() SITE_URL = settings.get('SITE_URL') dic['authorization_endpoint'] = SITE_URL + reverse( 'oidc_provider:authorize') dic['token_endpoint'] = SITE_URL + reverse('oidc_provider:token') dic['userinfo_endpoint'] = SITE_URL + reverse('oidc_provider:userinfo') dic['end_session_endpoint'] = SITE_URL + reverse( 'oidc_provider:logout') types_supported = [x[0] for x in Client.RESPONSE_TYPE_CHOICES] dic['response_types_supported'] = types_supported dic['jwks_uri'] = SITE_URL + reverse('oidc_provider:jwks') dic['id_token_signing_alg_values_supported'] = ['RS256'] # See: http://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes dic['subject_types_supported'] = ['public'] dic['token_endpoint_auth_methods_supported'] = [ 'client_secret_post', 'client_secret_basic' ] return JsonResponse(dic)
def get(self, request, *args, **kwargs): dic = dict() site_url = get_site_url(request=request) dic['issuer'] = get_issuer(site_url=site_url, request=request) dic['authorization_endpoint'] = site_url + reverse('oidc_provider:authorize') dic['token_endpoint'] = site_url + reverse('oidc_provider:token') dic['userinfo_endpoint'] = site_url + reverse('oidc_provider:userinfo') dic['end_session_endpoint'] = site_url + reverse('oidc_provider:end-session') types_supported = [x[0] for x in RESPONSE_TYPE_CHOICES] dic['response_types_supported'] = types_supported dic['jwks_uri'] = site_url + reverse('oidc_provider:jwks') dic['id_token_signing_alg_values_supported'] = ['HS256', 'RS256'] # See: http://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes dic['subject_types_supported'] = ['public'] dic['token_endpoint_auth_methods_supported'] = ['client_secret_post', 'client_secret_basic'] if settings.get('OIDC_SESSION_MANAGEMENT_ENABLE'): dic['check_session_iframe'] = site_url + reverse('oidc_provider:check-session-iframe') response = JsonResponse(dic) response['Access-Control-Allow-Origin'] = '*' return response
def create_id_token(user, aud, nonce): """ Receives a user object and aud (audience). Then creates the id_token dictionary. See: http://openid.net/specs/openid-connect-core-1_0.html#IDToken Return a dic. """ sub = settings.get('OIDC_IDTOKEN_SUB_GENERATOR')(user=user) expires_in = settings.get('OIDC_IDTOKEN_EXPIRE') # Convert datetimes into timestamps. now = timezone.now() iat_time = int(time.mktime(now.timetuple())) exp_time = int( time.mktime((now + timedelta(seconds=expires_in)).timetuple())) user_auth_time = user.last_login or user.date_joined auth_time = int(time.mktime(user_auth_time.timetuple())) dic = { 'iss': get_issuer(), 'sub': sub, 'aud': str(aud), 'exp': exp_time, 'iat': iat_time, 'auth_time': auth_time, } if nonce: dic['nonce'] = str(nonce) return dic
def get(self, request, *args, **kwargs): dic = dict() site_url = get_site_url(request=request) dic['issuer'] = get_issuer(site_url=site_url, request=request) dic['authorization_endpoint'] = site_url + reverse( 'oidc_provider:authorize') dic['token_endpoint'] = site_url + reverse('oidc_provider:token') dic['userinfo_endpoint'] = site_url + reverse('oidc_provider:userinfo') dic['end_session_endpoint'] = site_url + reverse( 'oidc_provider:logout') types_supported = [x[0] for x in RESPONSE_TYPE_CHOICES] dic['response_types_supported'] = types_supported dic['jwks_uri'] = site_url + reverse('oidc_provider:jwks') dic['id_token_signing_alg_values_supported'] = ['HS256', 'RS256'] # See: http://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes dic['subject_types_supported'] = ['public'] dic['token_endpoint_auth_methods_supported'] = [ 'client_secret_post', 'client_secret_basic' ] response = JsonResponse(dic) response['Access-Control-Allow-Origin'] = '*' return response
def get(self, request, *args, **kwargs): dic = dict() site_url = get_site_url(request=request) dic['issuer'] = get_issuer(site_url=site_url, request=request) dic['authorization_endpoint'] = site_url + reverse('oidc_provider:authorize') dic['token_endpoint'] = site_url + reverse('oidc_provider:token') dic['userinfo_endpoint'] = site_url + reverse('oidc_provider:userinfo') dic['end_session_endpoint'] = site_url + reverse('oidc_provider:logout') types_supported = [x[0] for x in RESPONSE_TYPE_CHOICES] dic['response_types_supported'] = types_supported dic['jwks_uri'] = site_url + reverse('oidc_provider:jwks') dic['id_token_signing_alg_values_supported'] = ['HS256', 'RS256'] # See: http://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes dic['subject_types_supported'] = ['public'] dic['token_endpoint_auth_methods_supported'] = [ 'client_secret_post', 'client_secret_basic' ] return JsonResponse(dic)
def create_id_token(user, aud, nonce): """ Receives a user object and aud (audience). Then creates the id_token dictionary. See: http://openid.net/specs/openid-connect-core-1_0.html#IDToken Return a dic. """ sub = settings.get('OIDC_IDTOKEN_SUB_GENERATOR')(user=user) expires_in = settings.get('OIDC_IDTOKEN_EXPIRE') # Convert datetimes into timestamps. now = timezone.now() iat_time = int(time.mktime(now.timetuple())) exp_time = int(time.mktime((now + timedelta(seconds=expires_in)).timetuple())) user_auth_time = user.last_login or user.date_joined auth_time = int(time.mktime(user_auth_time.timetuple())) dic = { 'iss': get_issuer(), 'sub': sub, 'aud': str(aud), 'exp': exp_time, 'iat': iat_time, 'auth_time': auth_time, } if nonce: dic['nonce'] = str(nonce) return dic
def create_id_token(token, user, aud, nonce='', at_hash='', request=None, scope=None): """ Creates the id_token dictionary. See: http://openid.net/specs/openid-connect-core-1_0.html#IDToken Return a dic. """ if scope is None: scope = [] sub = settings.get('OIDC_IDTOKEN_SUB_GENERATOR', import_str=True)(user=user) expires_in = settings.get('OIDC_IDTOKEN_EXPIRE') # Convert datetimes into timestamps. now = int(time.time()) iat_time = now exp_time = int(now + expires_in) user_auth_time = user.last_login or user.date_joined auth_time = int(dateformat.format(user_auth_time, 'U')) dic = { 'iss': get_issuer(request=request), 'sub': sub, 'aud': str(aud), 'exp': exp_time, 'iat': iat_time, 'auth_time': auth_time, } if nonce: dic['nonce'] = str(nonce) if at_hash: dic['at_hash'] = at_hash # Inlude (or not) user standard claims in the id_token. if settings.get('OIDC_IDTOKEN_INCLUDE_CLAIMS'): if settings.get('OIDC_EXTRA_SCOPE_CLAIMS'): custom_claims = settings.get('OIDC_EXTRA_SCOPE_CLAIMS', import_str=True)(token) claims = custom_claims.create_response_dic() else: claims = StandardScopeClaims(token).create_response_dic() dic.update(claims) dic = run_processing_hook(dic, 'OIDC_IDTOKEN_PROCESSING_HOOK', user=user, token=token, request=request) return dic
def create_id_token(user, aud, nonce='', at_hash='', request=None, scope=[]): """ Creates the id_token dictionary. See: http://openid.net/specs/openid-connect-core-1_0.html#IDToken Return a dic. """ sub = settings.get('OIDC_IDTOKEN_SUB_GENERATOR', import_str=True)(user=user) expires_in = settings.get('OIDC_IDTOKEN_EXPIRE') # Convert datetimes into timestamps. now = int(time.time()) iat_time = now exp_time = int(now + expires_in) user_auth_time = user.last_login or user.date_joined auth_time = int(dateformat.format(user_auth_time, 'U')) dic = { 'iss': get_issuer(request=request), 'sub': sub, 'aud': str(aud), 'exp': exp_time, 'iat': iat_time, 'auth_time': auth_time, } if nonce: dic['nonce'] = str(nonce) if at_hash: dic['at_hash'] = at_hash if settings.get('OIDC_EXTRA_SCOPE_CLAIMS'): custom_claims = settings.get('OIDC_EXTRA_SCOPE_CLAIMS', import_str=True)(user, scope) claims = custom_claims.create_response_dic() else: claims = StandardScopeClaims(user=user, scope=scope).create_response_dic() dic.update(claims) # modifies dic, adding all requested claims processing_hook = settings.get('OIDC_IDTOKEN_PROCESSING_HOOK') if isinstance(processing_hook, (list, tuple)): for hook in processing_hook: dic = settings.import_from_str(hook)(dic, user=user) else: dic = settings.import_from_str(processing_hook)(dic, user=user) return dic
def create_id_token(token, user, aud, nonce='', at_hash='', request=None, scope=None): """ Creates the id_token dictionary. See: http://openid.net/specs/openid-connect-core-1_0.html#IDToken Return a dic. """ if scope is None: scope = [] sub = settings.get('OIDC_IDTOKEN_SUB_GENERATOR', import_str=True)(user=user) expires_in = settings.get('OIDC_IDTOKEN_EXPIRE') # Convert datetimes into timestamps. now = int(time.time()) iat_time = now exp_time = int(now + expires_in) user_auth_time = user.last_login or user.date_joined auth_time = int(dateformat.format(user_auth_time, 'U')) dic = { 'iss': get_issuer(request=request), 'sub': sub, 'aud': str(aud), 'exp': exp_time, 'iat': iat_time, 'auth_time': auth_time, } if nonce: dic['nonce'] = str(nonce) if at_hash: dic['at_hash'] = at_hash # Inlude (or not) user standard claims in the id_token. if settings.get('OIDC_IDTOKEN_INCLUDE_CLAIMS'): if settings.get('OIDC_EXTRA_SCOPE_CLAIMS'): custom_claims = settings.get('OIDC_EXTRA_SCOPE_CLAIMS', import_str=True)(token) claims = custom_claims.create_response_dic() else: claims = StandardScopeClaims(token).create_response_dic() dic.update(claims) dic = run_processing_hook( dic, 'OIDC_IDTOKEN_PROCESSING_HOOK', user=user, token=token, request=request) return dic
def create_id_token(user, aud, nonce='', at_hash='', request=None, scope=None): """ Creates the id_token dictionary. See: http://openid.net/specs/openid-connect-core-1_0.html#IDToken Return a dic. """ if scope is None: scope = [] sub = settings.get('OIDC_IDTOKEN_SUB_GENERATOR', import_str=True)(user=user) expires_in = settings.get('OIDC_IDTOKEN_EXPIRE') # Convert datetimes into timestamps. now = int(time.time()) iat_time = now exp_time = int(now + expires_in) user_auth_time = user.last_login or user.date_joined auth_time = int(dateformat.format(user_auth_time, 'U')) dic = { 'iss': get_issuer(request=request), 'sub': sub, 'aud': str(aud), 'exp': exp_time, 'iat': iat_time, 'auth_time': auth_time, } if nonce: dic['nonce'] = str(nonce) if at_hash: dic['at_hash'] = at_hash if ('email' in scope) and getattr(user, 'email', None): dic['email'] = user.email processing_hook = settings.get('OIDC_IDTOKEN_PROCESSING_HOOK') if isinstance(processing_hook, (list, tuple)): for hook in processing_hook: dic = settings.import_from_str(hook)(dic, user=user) else: dic = settings.import_from_str(processing_hook)(dic, user=user) return dic
def create_id_token(user, aud, nonce, at_hash=None, request=None): """ Receives a user object and aud (audience). Then creates the id_token dictionary. See: http://openid.net/specs/openid-connect-core-1_0.html#IDToken Return a dic. """ sub = settings.get('OIDC_IDTOKEN_SUB_GENERATOR', import_str=True)(user=user) expires_in = settings.get('OIDC_IDTOKEN_EXPIRE') # Convert datetimes into timestamps. now = timezone.now() iat_time = int(time.mktime(now.timetuple())) exp_time = int( time.mktime((now + timedelta(seconds=expires_in)).timetuple())) user_auth_time = user.last_login or user.date_joined auth_time = int(time.mktime(user_auth_time.timetuple())) dic = { 'iss': get_issuer(request=request), 'sub': sub, 'aud': str(aud), 'exp': exp_time, 'iat': iat_time, 'auth_time': auth_time, } if nonce: dic['nonce'] = str(nonce) if at_hash: dic['at_hash'] = at_hash processing_hook = settings.get('OIDC_IDTOKEN_PROCESSING_HOOK') if isinstance(processing_hook, (list, tuple)): for hook in processing_hook: dic = settings.import_from_str(hook)(dic, user=user) else: dic = settings.import_from_str(processing_hook)(dic, user=user) return dic
def create_token(user, client, scope, id_token_dic=None): """ Create and populate a Token object. Return a Token object. """ token = Token() token.user = user token.client = client payload = { 'iss': get_issuer(request=None), 'client': client.name, 'scope': ' '.join(map(str, scope)), 'exp': timezone.now() + timedelta(seconds=settings.get('OIDC_TOKEN_EXPIRE')) } if id_token_dic is not None: payload['id_token_dic'] = id_token_dic if user is not None: payload['user'] = user kid = settings.get('OIDC_SECRET_KEY') myToken = jwt.encode(payload, settings.get('OIDC_SECRET_KEY'), headers={'kid': kid}) logging.error(myToken.decode()) token.access_token = myToken.decode() if id_token_dic is not None: token.id_token = id_token_dic token.refresh_token = uuid.uuid4().hex token.expires_at = timezone.now() + timedelta( seconds=settings.get('OIDC_TOKEN_EXPIRE')) token.token_refresh_expires_at = timezone.now() + timedelta( seconds=settings.get('OIDC_TOKEN_REFRESH_EXPIRE')) token.scope = scope return token
def create_id_token(user, aud, nonce='', at_hash='', request=None, scope=[]): """ Creates the id_token dictionary. See: http://openid.net/specs/openid-connect-core-1_0.html#IDToken Return a dic. """ sub = settings.get('OIDC_IDTOKEN_SUB_GENERATOR', import_str=True)(user=user) expires_in = settings.get('OIDC_IDTOKEN_EXPIRE') # Convert datetimes into timestamps. now = timezone.now() iat_time = int(time.mktime(now.timetuple())) exp_time = int(time.mktime((now + timedelta(seconds=expires_in)).timetuple())) user_auth_time = user.last_login or user.date_joined auth_time = int(time.mktime(user_auth_time.timetuple())) dic = { 'iss': get_issuer(request=request), 'sub': sub, 'aud': str(aud), 'exp': exp_time, 'iat': iat_time, 'auth_time': auth_time, } if nonce: dic['nonce'] = str(nonce) if at_hash: dic['at_hash'] = at_hash if ('email' in scope) and getattr(user, 'email', None): dic['email'] = user.email processing_hook = settings.get('OIDC_IDTOKEN_PROCESSING_HOOK') if isinstance(processing_hook, (list, tuple)): for hook in processing_hook: dic = settings.import_from_str(hook)(dic, user=user) else: dic = settings.import_from_str(processing_hook)(dic, user=user) return dic
def get(self, request, *args, **kwargs): dic = dict() site_url = get_site_url(request=request) dic['issuer'] = get_issuer(site_url=site_url, request=request) dic['authorization_endpoint'] = site_url + reverse( 'oidc_provider:authorize') dic['token_endpoint'] = site_url + reverse('oidc_provider:token') dic['userinfo_endpoint'] = site_url + reverse('oidc_provider:userinfo') dic['end_session_endpoint'] = site_url + reverse( 'oidc_provider:end-session') dic['introspection_endpoint'] = site_url + reverse( 'oidc_provider:token-introspection') types_supported = [ response_type.value for response_type in ResponseType.objects.all() ] dic['response_types_supported'] = types_supported dic['jwks_uri'] = site_url + reverse('oidc_provider:jwks') dic['id_token_signing_alg_values_supported'] = ['HS256', 'RS256'] # See: http://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes dic['subject_types_supported'] = ['public'] dic['token_endpoint_auth_methods_supported'] = [ 'client_secret_post', 'client_secret_basic' ] if settings.get('OIDC_SESSION_MANAGEMENT_ENABLE'): dic['check_session_iframe'] = site_url + reverse( 'oidc_provider:check-session-iframe') if settings.get('OIDC_ACR_VALUES'): dic['acr_values_supported'] = settings.get('OIDC_ACR_VALUES') response = JsonResponse(dic) response['Access-Control-Allow-Origin'] = '*' return response
def create_logout_token(user, aud, sid, request=None) -> dict: """ Creates the logout token dictionary. See: https://openid.net/specs/openid-connect-backchannel-1_0.html#LogoutToken Return a dic. """ sub = settings.get( 'OIDC_IDTOKEN_SUB_GENERATOR', import_str=True, )(user=user) dic = { 'iss': get_issuer(request=request), 'sub': sub, 'aud': str(aud), 'iat': int(time.time()), 'jti': md5(uuid.uuid4().hex.encode()).hexdigest(), 'events': 'http://schemas.openid.net/event/backchannel-logout', 'sid': sid, } return dic
def create_response_dic(cls): dic = {} dic['issuer'] = get_issuer() SITE_URL = settings.get('SITE_URL') dic['authorization_endpoint'] = SITE_URL + reverse('oidc_provider:authorize') dic['token_endpoint'] = SITE_URL + reverse('oidc_provider:token') dic['userinfo_endpoint'] = SITE_URL + reverse('oidc_provider:userinfo') from oidc_provider.models import Client types_supported = [x[0] for x in Client.RESPONSE_TYPE_CHOICES] dic['response_types_supported'] = types_supported # TODO: #dic['jwks_uri'] = None # See: http://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes dic['subject_types_supported'] = ['public'] return dic
def create_response_dic(cls): dic = {} dic['issuer'] = get_issuer() SITE_URL = settings.get('SITE_URL') dic['authorization_endpoint'] = SITE_URL + reverse( 'oidc_provider:authorize') dic['token_endpoint'] = SITE_URL + reverse('oidc_provider:token') dic['userinfo_endpoint'] = SITE_URL + reverse('oidc_provider:userinfo') from oidc_provider.models import Client types_supported = [x[0] for x in Client.RESPONSE_TYPE_CHOICES] dic['response_types_supported'] = types_supported # TODO: #dic['jwks_uri'] = None # See: http://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes dic['subject_types_supported'] = ['public'] return dic
def test_get_issuer(self): issuer = get_issuer() self.assertEqual(issuer, settings.SITE_URL + '/openid')
def create_response_uri(self, allow): if not allow: raise AuthorizeError( self.params.redirect_uri, 'access_denied', self.grant_type) try: self.validate_params() if self.grant_type == 'authorization_code': code = create_code( user=self.request.user, client=self.client, scope=self.params.scope) code.save() # Create the response uri. uri = self.params.redirect_uri + '?code={0}'.format(code.code) else: # Implicit Flow # TODO refactor since it's the same as the token endpoint sub = settings.get('OIDC_IDTOKEN_SUB_GENERATOR')( user=self.request.user) id_token_dic = create_id_token( iss=get_issuer(), sub=sub, aud=self.client.client_id, auth_time=self.request.user.last_login) token = create_token( user=self.request.user, client=self.client, id_token_dic=id_token_dic, scope=self.params.scope) # Store the token. token.save() id_token = encode_id_token( id_token_dic, self.client.client_secret) # Create the response uri. uri = self.params.redirect_uri + \ '#token_type={0}&id_token={1}&expires_in={2}'.format( 'bearer', id_token, 60 * 10, ) # Check if response_type is 'id_token token' then # add access_token to the fragment. if self.params.response_type == 'id_token token': uri += '&access_token={0}'.format(token.access_token) except: raise AuthorizeError( self.params.redirect_uri, 'server_error', self.grant_type) # Add state if present. uri += ('&state={0}'.format(self.params.state) if self.params.state else '') return uri