def test_additional_idtoken_processing_hook_two_elements_in_tuple(self): """ Test custom function for setting OIDC_IDTOKEN_PROCESSING_HOOK. """ code = self._create_code() post_data = self._auth_code_post_data(code=code.code) response = self._post_request(post_data) response_dic = json.loads(response.content.decode('utf-8')) id_token = JWT().unpack( response_dic['id_token'].encode('utf-8')).payload() self.assertEqual(id_token.get('test_idtoken_processing_hook'), FAKE_RANDOM_STRING) self.assertEqual( id_token.get('test_idtoken_processing_hook_user_email'), self.user.email) self.assertEqual(id_token.get('test_idtoken_processing_hook2'), FAKE_RANDOM_STRING) self.assertEqual( id_token.get('test_idtoken_processing_hook_user_email2'), self.user.email)
def test_access_token_contains_nonce(self): """ If present in the Authentication Request, Authorization Servers MUST include a nonce Claim in the ID Token with the Claim Value being the nonce value sent in the Authentication Request. If the client does not supply a nonce parameter, it SHOULD not be included in the `id_token`. See http://openid.net/specs/openid-connect-core-1_0.html#IDToken """ code = self._create_code() post_data = self._auth_code_post_data(code=code.code) response = self._post_request(post_data) response_dic = json.loads(response.content.decode('utf-8')) id_token = JWT().unpack(response_dic['id_token'].encode('utf-8')).payload() self.assertEqual(id_token.get('nonce'), FAKE_NONCE) # Client does not supply a nonce parameter. code.nonce = '' code.save() response = self._post_request(post_data) response_dic = json.loads(response.content.decode('utf-8')) id_token = JWT().unpack(response_dic['id_token'].encode('utf-8')).payload() self.assertEqual(id_token.get('nonce'), None)
def test_access_token_contains_nonce(self): """ If present in the Authentication Request, Authorization Servers MUST include a nonce Claim in the ID Token with the Claim Value being the nonce value sent in the Authentication Request. If the client does not supply a nonce parameter, it SHOULD not be included in the `id_token`. See http://openid.net/specs/openid-connect-core-1_0.html#IDToken """ code = self._create_code() post_data = self._auth_code_post_data(code=code.code) response = self._post_request(post_data) response_dic = json.loads(response.content.decode('utf-8')) id_token = JWT().unpack( response_dic['id_token'].encode('utf-8')).payload() self.assertEqual(id_token.get('nonce'), FAKE_NONCE) # Client does not supply a nonce parameter. code.nonce = '' code.save() response = self._post_request(post_data) response_dic = json.loads(response.content.decode('utf-8')) id_token = JWT().unpack( response_dic['id_token'].encode('utf-8')).payload() self.assertEqual(id_token.get('nonce'), None)
def test_additional_idtoken_processing_hook_one_element_in_list(self): """ Test custom function for setting OIDC_IDTOKEN_PROCESSING_HOOK. """ code = self._create_code() post_data = self._auth_code_post_data(code=code.code) response = self._post_request(post_data) response_dic = json.loads(response.content.decode('utf-8')) id_token = JWT().unpack(response_dic['id_token'].encode('utf-8')).payload() self.assertEqual(id_token.get('test_idtoken_processing_hook'), FAKE_RANDOM_STRING) self.assertEqual(id_token.get('test_idtoken_processing_hook_user_email'), self.user.email)
def save_profile(backend, user, response, *args, **kwargs): # make sure there is a UserProfile object for the given User profile, created = UserProfile.objects.get_or_create(user=user) if backend.name == 'verifymyidentity-openidconnect': # Save the id_token 'sub' to the UserProfile.subject if 'id_token' in response.keys(): id_token = response.get('id_token') id_token_payload = JWT().unpack(id_token).payload() profile.verifying_agent_email = id_token_payload.get( 'verifying_agent_email') profile.save() logger.info('Verifying Agent Email set as %r from %r' % (profile.verifying_agent_email, id_token_payload.get("verifying_agent_email")))
def client_id_from_id_token(id_token): """ Extracts the client id from a JSON Web Token (JWT). Returns a string or None. """ payload = JWT().unpack(id_token).payload() return payload.get('aud', None)
def __get_kid_from_api_response_headers(headers): """ Gets `kid` property from a JWT token within the headers of a LaunchKey API response. :param headers: Response headers :return: string of the `kid` :raises launchkey.exceptions.UnexpectedAPIResponse: if unable to unpack the JWT or if the JWT header does not exist :raises launchkey.exceptions.JWTValidationFailure: if `kid` is missing or invalid """ try: jwt = headers.get("X-IOV-JWT") jwt_headers = JWT().unpack(jwt).headers except (BadSyntax, IndexError, ValueError): raise UnexpectedAPIResponse("JWT was missing or malformed in API " "response.") kid = jwt_headers.get("kid") if not isinstance(kid, six.string_types): raise JWTValidationFailure("`kid` header in JWT was missing or" " invalid.") return kid
def get_upstream_aal(backend, user, response, *args, **kwargs): """Get the upstream information from supported upstream IdP""" if backend.name in ('okta-openidconnect',): # Save the id_token 'sub' to the UpstreamIdentityProviderToUser model. if 'id_token' in response.keys(): id_token = response.get('id_token') id_token_payload = JWT().unpack(id_token).payload() up_aal, created = UpstreamIdentityProviderUserAuthenticatorAssurance.objects.get_or_create(user=user) up_aal.upstream_idp_sub = id_token_payload['sub'] up_aal.upstream_idp_vendor = backend.name up_aal.upstream_idp_iss = id_token_payload.get('iss', '') up_aal.upstream_idp_aud = id_token_payload.get('aud', '') up_aal.name = "%s %s" % (user.first_name.title(), user.last_name.title()) up_aal.email = user.email up_aal.amr = json.dumps(id_token_payload.get('amr', '[]')) up_aal.save() if up_aal.amr == '[]': logger.debug("No 'amr' claim found in id_token")
def save_profile(backend, user, response, *args, **kwargs): # make sure there is a UserProfile object for the given User profile, created = UserProfile.objects.get_or_create(user=user) if backend.name == 'verifymyidentity-openidconnect': # Save the id_token 'sub' to the UserProfile.subject if 'id_token' in response.keys(): id_token = response.get('id_token') id_token_payload = JWT().unpack(id_token).payload() profile.subject = id_token_payload.get('sub') profile.preferred_username = id_token_payload.get( 'preferred_username') profile.save() profile.user.first_name = id_token_payload.get('given_name') profile.user.last_name = id_token_payload.get('family_name') profile.user.email = id_token_payload.get('email') profile.user.save()
def client_id_from_id_token(id_token): """ Extracts the client id from a JSON Web Token (JWT). Returns a string or None. """ payload = JWT().unpack(id_token).payload() aud = payload.get('aud', None) if aud is None: return None if isinstance(aud, list): return aud[0] return aud
def test_id_token_contains_at_hash(self): """ If access_token is included, the id_token SHOULD contain an at_hash. """ code = self._create_code() post_data = self._auth_code_post_data(code=code.code) response = self._post_request(post_data) response_dic = json.loads(response.content.decode('utf-8')) id_token = JWT().unpack(response_dic['id_token'].encode('utf-8')).payload() self.assertTrue(id_token.get('at_hash'))
def test_custom_sub_generator(self): """ Test custom function for setting OIDC_IDTOKEN_SUB_GENERATOR. """ code = self._create_code() post_data = self._auth_code_post_data(code=code.code) response = self._post_request(post_data) response_dic = json.loads(response.content.decode('utf-8')) id_token = JWT().unpack(response_dic['id_token'].encode('utf-8')).payload() self.assertEqual(id_token.get('sub'), self.user.email)
def authenticated_home(request): name = _('Authenticated Home') if request.user.is_authenticated: # Get the ID Token and parse it. try: vmi = request.user.social_auth.filter( provider='verifymyidentity-openidconnect')[0] extra_data = vmi.extra_data if 'id_token' in vmi.extra_data.keys(): id_token = extra_data.get('id_token') parsed_id_token = JWT().unpack(id_token) parsed_id_token = parsed_id_token.payload() except Exception: id_token = "No ID token." parsed_id_token = {'sub': '', 'ial': '1'} hp, g_o_c = HIEProfile.objects.get_or_create(user=request.user) if parsed_id_token.get('ial') not in ('2', '3'): # redirect to get verified messages.warning( request, 'Your identity has not been verified. \ This must be completed prior to access to personal health information.' ) try: profile = request.user.userprofile except Exception: profile = None # this is a GET context = { 'name': name, 'profile': profile, 'hp': hp, 'id_token': id_token, 'id_token_payload': parsed_id_token } template = 'authenticated-home.html' else: name = ('home') context = {'name': name} template = 'index.html' return render(request, template, context)
def authenticated_home(request): name = _('Authenticated Home') if request.user.is_authenticated: # Get the ID Token and parse it. try: vmi = request.user.social_auth.filter( provider='verifymyidentity-openidconnect')[0] extra_data = vmi.extra_data if 'id_token' in vmi.extra_data.keys(): id_token = extra_data.get('id_token') parsed_id_token = JWT().unpack(id_token) parsed_id_token = parsed_id_token.payload() except Exception: id_token = "No ID token." parsed_id_token = {'sub': '', 'ial': '1'} if parsed_id_token.get('ial') not in ('2', '3'): # redirect to get verified messages.warning( request, 'Your identity has not been verified. \ This must be completed prior to access to Personal Health Information.' ) try: profile = request.user.userprofile except Exception: profile = None # this is a GET context = { 'name': name, 'profile': profile, 'id_token': id_token, 'id_token_payload': parsed_id_token } template = settings.HOMEPAGE_AUTHENTICATED_TEMPLATE else: name = ('home') context = {'name': name} template = settings.HOMEPAGE_TEMPLATE return render(request, template, context)
def save_mrn(backend, user, response, *args, **kwargs): # make sure there is a UserProfile object for the given User profile, created = HIEProfile.objects.get_or_create(user=user) if backend.name == 'verifymyidentity-openidconnect': # Save the id_token 'sub' to the UserProfile.subject if 'id_token' in response.keys(): id_token = response.get('id_token') id_token_payload = JWT().unpack(id_token).payload() print(id_token_payload) docs = id_token_payload.get('document') print(docs) if docs: for doc in docs: if doc.get('issuer') == "HIXNY" and doc.get( 'type') == "MPI": profile.mrn = doc.get('num') profile.save() logger.info( 'MPI issued by %s sourced for %s %s from %s' % (doc.get('issuer'), user.first_name, user.last_name, backend.name))
def get_upstream_sub(backend, user, response, *args, **kwargs): """Get the upstream information from supported upstream IdP""" if backend.name in ('okta-openidconnect',): # Save the id_token 'sub' to the UpstreamIdentityProviderToUser model. if 'id_token' in response.keys(): id_token = response.get('id_token') id_token_payload = JWT().unpack(id_token).payload() if not UpstreamIdentityProviderToUser.objects.filter(user=user, upstream_idp_sub=id_token_payload['sub'], upstream_idp_vendor=backend.name).exists(): uidp2u = UpstreamIdentityProviderToUser.objects.create( user=user, upstream_idp_sub=id_token_payload['sub'], upstream_idp_vendor=backend.name, upstream_idp_iss=id_token_payload.get('iss', ''), upstream_idp_aud=id_token_payload.get('aud', ''), name="%s %s" % (user.first_name.title(), user.last_name.title()), email=user.email) logger.debug("Upstream IdP %s was autogenerated." % (uidp2u)) if settings.SOCIAL_AUTH_OKTA_OPENIDCONNECT_AUTO_IAL2: idd, created = IdentityAssuranceLevelDocumentation.objects.get_or_create(subject_user=user, evidence="IAL2-ON-FILE") idd.note = "Autogenerated from business rules." idd.save() logger.debug("IAL2 %s was autogenerated." % (idd))