def test_pack_jwt(): _jwt = JWT(**{"alg": "none", "cty": "jwt"}) jwt = _jwt.pack(parts=[{"iss": "joe", "exp": 1300819380, "http://example.com/is_root": True}, ""]) p = jwt.split(b'.') assert len(p) == 3
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 wrapper(request, *args, **kwargs): if request.user.is_authenticated: 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', "note": "No ID token for this user" } if parsed_id_token['ial'] not in ('2', '3'): msg = _( "%s %s was defined access due to insufficient identity assurance level (IAL). Subject=%s" "" % (request.user.first_name, request.user.last_name, parsed_id_token['sub'])) logger.info(msg) response_string = _( """Your identity assurance level (IAL) of 1 is insufficient for this action.""" ) return HttpResponseForbidden(response_string) return func(request, *args, **kwargs)
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 test_client_secret_jwt(self, client): client.token_endpoint = "https://example.com/token" client.provider_info = { 'issuer': 'https://example.com/', 'token_endpoint': "https://example.com/token" } csj = ClientSecretJWT(client) cis = AccessTokenRequest() csj.construct(cis, algorithm="HS256", authn_endpoint='userinfo') assert cis["client_assertion_type"] == JWT_BEARER assert "client_assertion" in cis cas = cis["client_assertion"] _jwt = JWT().unpack(cas) jso = _jwt.payload() assert _eq(jso.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"]) assert _jwt.headers == {'alg': 'HS256'} _rj = JWS() info = _rj.verify_compact( cas, [SYMKey(k=b64e(as_bytes(client.client_secret)))]) assert _eq(info.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"]) assert info['aud'] == [client.provider_info['issuer']]
def test_construct(self, client): _key = rsa_load(os.path.join(BASE_PATH, "data/keys/rsa.key")) kc_rsa = KeyBundle([{ "key": _key, "kty": "RSA", "use": "ver" }, { "key": _key, "kty": "RSA", "use": "sig" }]) client.keyjar[""] = kc_rsa client.token_endpoint = "https://example.com/token" client.provider_info = { 'issuer': 'https://example.com/', 'token_endpoint': "https://example.com/token" } cis = AccessTokenRequest() pkj = PrivateKeyJWT(client) http_args = pkj.construct(cis, algorithm="RS256", authn_endpoint='token') assert http_args == {} cas = cis["client_assertion"] _jwt = JWT().unpack(cas) jso = _jwt.payload() assert _eq(jso.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"]) assert _jwt.headers == {'alg': 'RS256'} assert jso['aud'] == [client.provider_info['token_endpoint']]
def callback(request): response = OrderedDict() if 'error' in request.GET: return render(request, "access-denied.html", {"error": request.GET.get("error")}) oas = OAuth2Session(request.session['client_id'], redirect_uri=request.session['redirect_uri']) host = settings.HOSTNAME_URL if not(host.startswith("http://") or host.startswith("https://")): host = "https://%s" % (host) auth_uri = host + request.get_full_path() token_uri = host + reverse('oauth2_provider:token') try: token = oas.fetch_token(token_uri, client_secret=get_client_secret(), authorization_response=auth_uri) except MissingTokenError: logmsg = "Failed to get token from %s" % (request.session['token_uri']) logger.error(logmsg) return JsonResponse({'error': 'Failed to get token from', 'code': 'MissingTokenError', 'help': 'Try authorizing again.'}, status=500) request.session['token'] = token response['token_response'] = OrderedDict() for k, v in token.items(): if k != "scope": response['token_response'][k] = v else: response['token_response'][k] = ' '.join(v) response['test_page'] = host + reverse('testclient_home') parsed_id_token = JWT().unpack(response['token_response']['id_token']) parsed_id_token = parsed_id_token.payload() response['id_token_payload'] = parsed_id_token return success(request, response)
def create_or_update_org(backend, user, response, *args, **kwargs): if backend.name == 'verifymyidentity-openidconnect': if 'id_token' in response.keys(): id_token = response.get('id_token') parsed_id_token = JWT().unpack(id_token) payload = parsed_id_token.payload() org_slugs = [] if 'organization_agent' in payload: for organization in payload['organization_agent']: org, g_o_c = Organization.objects.get_or_create( slug=organization['slug']) org_slugs.append(organization['slug']) org.name = organization['name'] org.sub = organization['sub'] org.website = organization['website'] org.phone = organization['phone_number'] org.picture_url = organization.get('picture', None) org.agents.add(user) # Make sure the user is an org agent. org.save() # remove an agent from organization if they have been removed. all_orgs = Organization.objects.all() for o in all_orgs: if o.slug not in org_slugs: o.agents.remove(user) o.save()
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_pack_jwt(): _jwt = JWT(**{"alg": "none", "cty": "jwt"}) jwt = _jwt.pack(parts=[{"iss": "joe", "exp": 1300819380, "http://example.com/is_root": True}, ""]) p = jwt.split('.') assert len(p) == 3
def test_unpack_pack(): _jwt = JWT(**{"alg": "none"}) payload = {"iss": "joe", "exp": 1300819380, "http://example.com/is_root": True} jwt = _jwt.pack(parts=[payload, ""]) repacked = JWT().unpack(jwt).pack() assert jwt == repacked
def verify_id_token(instance, check_hash=False, **kwargs): # Try to decode the JWT, checks the signature args = {} for arg in TOKEN_VERIFY_ARGS: try: args[arg] = kwargs[arg] except KeyError: pass _jws = str(instance["id_token"]) # It can be encrypted, so try to decrypt first _jwe = JWE_factory(_jws) if _jwe is not None: try: _jws = _jwe.decrypt(keys=kwargs["keyjar"].get_decrypt_key()) except JWEException as err: raise VerificationError("Could not decrypt id_token", err) _packer = JWT() _body = _packer.unpack(_jws).payload() if "keyjar" in kwargs: try: if _body["iss"] not in kwargs["keyjar"]: raise ValueError("Unknown issuer") except KeyError: raise MissingRequiredAttribute("iss") if _jwe is not None: # Use the original encrypted token to set correct headers idt = IdToken().from_jwt(str(instance["id_token"]), **args) else: idt = IdToken().from_jwt(_jws, **args) if not idt.verify(**kwargs): raise VerificationError("Could not verify id_token", idt) if check_hash: _alg = idt.jws_header["alg"] if _alg != "none": hfunc = "HS" + _alg[-3:] else: # This is allowed only for `code` and it needs to be checked by a Client hfunc = None if "access_token" in instance and hfunc is not None: if "at_hash" not in idt: raise MissingRequiredAttribute("Missing at_hash property", idt) if idt["at_hash"] != jws.left_hash(instance["access_token"], hfunc): raise AtHashError("Failed to verify access_token hash", idt) if "code" in instance and hfunc is not None: if "c_hash" not in idt: raise MissingRequiredAttribute("Missing c_hash property", idt) if idt["c_hash"] != jws.left_hash(instance["code"], hfunc): raise CHashError("Failed to verify code hash", idt) return idt
def get_username(strategy, details, backend, user, response, *args, **kwargs): # The subject id is the username. if backend.name == 'verifymyidentity-openidconnect': if 'id_token' in response.keys(): id_token = response.get('id_token') parsed_id_token = JWT().unpack(id_token) payload = parsed_id_token.payload() return {'username': payload['sub']} return
def test_unpack_str(): _jwt = JWT(**{"alg": "none"}) payload = {"iss": "joe", "exp": 1300819380, "http://example.com/is_root": True} jwt = _jwt.pack(parts=[payload, ""]) _jwt2 = JWT().unpack(jwt) assert _jwt2 out_payload = _jwt2.payload()
def verify_id_token(instance, check_hash=False, **kwargs): # Try to decode the JWT, checks the signature args = {} for arg in ["key", "keyjar", "algs", "sender"]: try: args[arg] = kwargs[arg] except KeyError: pass _jws = str(instance["id_token"]) # It can be encrypted, so try to decrypt first _jwe = JWE_factory(_jws) if _jwe is not None: try: _jws = _jwe.decrypt(keys=kwargs['keyjar'].get_decrypt_key()) except JWEException as err: raise VerificationError("Could not decrypt id_token", err) _packer = JWT() _body = _packer.unpack(_jws).payload() if 'keyjar' in kwargs: try: if _body['iss'] not in kwargs['keyjar']: raise ValueError('Unknown issuer') except KeyError: raise MissingRequiredAttribute('iss') if _jwe is not None: # Use the original encrypted token to set correct headers idt = IdToken().from_jwt(str(instance['id_token']), **args) else: idt = IdToken().from_jwt(_jws, **args) if not idt.verify(**kwargs): raise VerificationError("Could not verify id_token", idt) if check_hash: _alg = idt.jws_header["alg"] # What if _alg == 'none' hfunc = "HS" + _alg[-3:] if "access_token" in instance: if "at_hash" not in idt: raise MissingRequiredAttribute("Missing at_hash property", idt) if idt["at_hash"] != jws.left_hash(instance["access_token"], hfunc): raise AtHashError("Failed to verify access_token hash", idt) if "code" in instance: if "c_hash" not in idt: raise MissingRequiredAttribute("Missing c_hash property", idt) if idt["c_hash"] != jws.left_hash(instance["code"], hfunc): raise CHashError("Failed to verify code hash", idt) return idt
def save_profile(backend, user, response, *args, **kwargs): if backend.name == 'verifymyidentity-openidconnect': profile, g_o_c = UserProfile.objects.get_or_create(user=user) if 'id_token' in response.keys(): id_token = response.get('id_token') parsed_id_token = JWT().unpack(id_token) payload = parsed_id_token.payload() if 'given_name' in payload: profile.user.first_name = payload['given_name'] if 'family_name' in payload: profile.user.last_name = payload['family_name'] if 'sub' in payload: profile.subject = payload['sub'] if 'nickname' in payload: profile.nickname = payload['nickname'] if 'phone_number' in payload: profile.mobile_phone_number = payload['phone_number'] if 'birthdate' in payload: if payload['birthdate'] not in ("None", ""): profile.birth_date = payload['birthdate'] if 'gender' in payload: profile.gender = payload['gender'] if 'email_verified' in payload: profile.email_verified = payload['email_verified'] if 'gender_identity' in payload: profile.gender_identity = payload['gender_identity'] if 'middle_name' in payload: profile.middle_name = payload['middle_name'] if 'phone_verified' in payload: profile.phone_verified = payload['phone_verified'] if 'ial' in payload: profile.identity_assurance_level = payload['ial'] if ('picture' in payload and 'None' not in payload['picture'] and 'no-img' not in payload['picture']): profile.picture_url = payload['picture'] profile.most_recent_id_token_payload = json.dumps(payload, indent=4) profile.user.save() profile.save()
def test_unpack_pack(): _jwt = JWT(**{"alg": "none"}) payload = { "iss": "joe", "exp": 1300819380, "http://example.com/is_root": True } jwt = _jwt.pack(parts=[payload, ""]) repacked = JWT().unpack(jwt).pack() assert jwt == repacked
def jwt_payload(request): if 'jwt' not in request.GET: return JsonResponse({"error": "you just supply a jwt as a GET parmeter."}) myjwt = request.GET.get("jwt") try: parsed_id_token = JWT().unpack(myjwt) parsed_id_token = parsed_id_token.payload() except Exception: parsed_id_token = { "error": "you just supply a valid jwt as a GET parmeter."} return JsonResponse(parsed_id_token)
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 test_additional_idtoken_processing_hook(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)
def unpack_jwt(jwt: str, keys: list): """ Unpacks a signed jwt question :type keys: list[str] :rtype: dict[str, str] :param jwt: A signed jwt containing the question (the idp, id and redirect_endpoint) :param keys: A list of keys to use when verifying the signature :return: The unpacked jwt """ JWTHandler._verify_jwt(jwt, keys) _jwt = JWT().unpack(jwt) jso = _jwt.payload() if "sp" not in jso or "idp" not in jso or "ticket" not in jso: return None return jso
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 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 test_pack_unpack(): _jwt = JWT(**{"alg": "none"}) payload = {"iss": "joe", "exp": 1300819380, "http://example.com/is_root": True} jwt = _jwt.pack(parts=[payload, ""]) _jwt2 = JWT().unpack(jwt) assert _jwt2 out_payload = _jwt2.payload() assert _eq(out_payload.keys(), ["iss", "exp", "http://example.com/is_root"]) assert out_payload["iss"] == payload["iss"] assert out_payload["exp"] == payload["exp"] assert out_payload["http://example.com/is_root"] == payload[ "http://example.com/is_root"]
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 validate_and_decode(self, token): """ Check if a message sent by the tool is valid. From https://www.imsglobal.org/spec/security/v1p0/#using-oauth-2-0-client-credentials-grant: The authorization server decodes the JWT and MUST validate the values for the iss, sub, exp, aud and jti claims. """ try: # Get KID from JWT header jwt = JWT().unpack(token) # Verify message signature message = JWS().verify_compact(token, keys=self._get_keyset( jwt.headers.get('kid'))) # If message is valid, check expiration from JWT if 'exp' in message and message['exp'] < time.time(): raise exceptions.TokenSignatureExpired() # TODO: Validate other JWT claims # Else returns decoded message return message except NoSuitableSigningKeys as err: raise exceptions.NoSuitableKeys() from err except BadSyntax as err: raise exceptions.MalformedJwtToken() from err except WrongNumberOfParts as err: raise exceptions.MalformedJwtToken() from err
def test_idtoken_at_hash(self): """ Implicit client requesting `id_token` should not receive `at_hash` in `id_token`. """ data = { 'client_id': self.client_no_access.client_id, 'redirect_uri': self.client_no_access.default_redirect_uri, 'response_type': next(self.client_no_access.response_type_values()), 'scope': 'openid email', 'state': self.state, 'nonce': self.nonce, 'allow': 'Accept', } response = self._auth_request('post', data, is_user_authenticated=True) self.assertIn('id_token', response['Location']) # obtain `id_token` portion of Location components = urlsplit(response['Location']) fragment = parse_qs(components[4]) id_token = JWT().unpack(fragment["id_token"][0].encode('utf-8')).payload() self.assertNotIn('at_hash', id_token)
def test_make_id_token(self): self.srv.keyjar["http://oic.example/idp"] = KC_RSA session = {"sub": "user0", "client_id": "http://oic.example/rp"} issuer = "http://oic.example/idp" code = "abcdefghijklmnop" _idt = self.srv.make_id_token(session, loa="2", issuer=issuer, code=code, access_token="access_token") algo = "RS256" ckey = self.srv.keyjar.get_signing_key(alg2keytype(algo), issuer) _signed_jwt = _idt.to_jwt(key=ckey, algorithm="RS256") idt = IdToken().from_jwt(_signed_jwt, keyjar=self.srv.keyjar) _jwt = JWT().unpack(_signed_jwt) lha = left_hash(code.encode("utf-8"), func="HS" + _jwt.headers["alg"][-3:]) assert lha == idt["c_hash"] atr = AccessTokenResponse(id_token=_signed_jwt, access_token="access_token", token_type="Bearer") atr["code"] = code assert atr.verify(keyjar=self.srv.keyjar)
def test_get_user_by_id_django_user_exists(self): settings.OIDC_AUTH = {'OIDC_AUDIENCES': ['client_id']} UserModel = get_user_model() existing_user = UserModel.objects.create(username='******') # No or incorrect KeycloakModel mapping of this user to the Keycloak UID token = { 'sub': 'uid', 'preferred_username': '******', 'aud': ['client_id'], } request = MagicMock() request.session.get.return_value = JWT().pack([token], JWT_HEADERS) user = backend.get_user_by_id(request, token) self.assertNotEqual(user, existing_user) with self.assertRaises(UserModel.DoesNotExist): UserModel.objects.get(id=existing_user.id) self.assertEqual(user.username, 'username') self.assertEqual(user.keycloak.UID, 'uid')
def get_id_token_payload(user): # Get the ID Token and parse it. try: vmi = user.social_auth.filter(provider='vmi')[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() else: parsed_id_token = {'sub': '', 'ial': '1'} except Exception: parsed_id_token = {'sub': '', 'ial': '1'} return parsed_id_token
def test_get_user_by_id(self, mLoadRoles, mUserData): settings.OIDC_AUTH = {'OIDC_AUDIENCES': ['client_id']} token = { 'sub': 'uid', 'preferred_username': '******', 'aud': ['client_id'], 'realm_access': { 'roles': ['one', 'two', 'three'] } } request = MagicMock() request.session.get.return_value = JWT().pack([token], JWT_HEADERS) user = backend.get_user_by_id(request, token) self.assertEqual(user.username, 'username') self.assertEqual(user.keycloak.UID, 'uid') self.assertEqual(user.first_name, '') self.assertEqual(user.last_name, '') self.assertEqual(user.email, '') self.assertFalse(user.is_staff) self.assertFalse(user.is_superuser) expected = [call(user, ['one', 'two', 'three'])] self.assertEqual(mLoadRoles.mock_calls, expected) expected = [call(user, token)] self.assertEqual(mUserData.mock_calls, expected)
def set_user_type(backend, user, response, *args, **kwargs): user_type = "M" up, g_o_c = UserProfile.objects.get_or_create(user=user) if backend.name == 'vmi': user_type = "M" up, g_o_c = UserProfile.objects.get_or_create(user=user) if 'id_token' in response.keys(): id_token = response.get('id_token') parsed_id_token = JWT().unpack(id_token) payload = parsed_id_token.payload() if 'organization_agent' in payload: if len(payload['organization_agent']) > 0: user_type = "O" up.user_type = user_type up.save()
def test_construct(self, client): _key = rsa_load( os.path.join(BASE_PATH, "data/keys/rsa.key")) kc_rsa = KeyBundle([{"key": _key, "kty": "RSA", "use": "ver"}, {"key": _key, "kty": "RSA", "use": "sig"}]) client.keyjar[""] = kc_rsa client.token_endpoint = "https://example.com/token" cis = AccessTokenRequest() pkj = PrivateKeyJWT(client) http_args = pkj.construct(cis, algorithm="RS256") assert http_args == {} cas = cis["client_assertion"] _jwt = JWT().unpack(cas) jso = _jwt.payload() assert _eq(jso.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"]) assert _jwt.headers == {'alg': 'RS256'}
def map_user(request): if (request.authorization is not None): if (JWSig().unpack(request.authorization.params).valid()): username = JWT().unpack(request.authorization.params).payload()['preferred_username'] #map username to userid user = DBSession.query(User).filter_by(name=username).first() return user return None
def id_token_payload_json(request): 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', "note": "No ID token for this user" } return JsonResponse(parsed_id_token)
def test_client_secret_jwt(self, client): client.token_endpoint = "https://example.com/token" csj = ClientSecretJWT(client) cis = AccessTokenRequest() http_args = csj.construct(cis, algorithm="HS256") assert cis["client_assertion_type"] == JWT_BEARER assert "client_assertion" in cis cas = cis["client_assertion"] _jwt = JWT().unpack(cas) jso = _jwt.payload() assert _eq(jso.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"]) assert _jwt.headers == {'alg': 'HS256'} _rj = JWS() info = _rj.verify_compact(cas, [SYMKey(key=client.client_secret)]) assert _eq(info.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"])
def test_construct_authz_req_with_request_object(self, tmpdir): path = tmpdir.strpath request_uri_args = { "local_dir": path, "base_path": "http://example.com/" } areq = self.client.construct_AuthorizationRequest(request_method="file", **request_uri_args) p = urlparse(areq["request_uri"]) local_path = os.path.join(path, p.path.lstrip("/")) with open(local_path) as f: data = f.read() jwt = JWT().unpack(data) payload = jwt.payload() assert payload["redirect_uri"] == "http://example.com/redirect" assert payload["client_id"] == CLIENT_ID assert "nonce" in payload os.remove(local_path)
def assert_registstration_req(self, request, sign_key_str): split_path = request.path_url.lstrip("/").split("/") assert len(split_path) == 2 jwks = split_path[1] # Verify signature public_key = import_rsa_key(private_to_public_key(sign_key_str)) sign_key = RSAKey().load_key(public_key) sign_key.use = "sig" _jw = jws.factory(jwks) _jw.verify_compact(jwks, [sign_key]) # Verify JWT _jwt = JWT().unpack(jwks) consent_args = _jwt.payload() assert "attr" in consent_args assert "redirect_endpoint" in consent_args assert "id" in consent_args
def verify_poet_via_url(my_jws): # load the Signed JWT (JWS) my_jws = my_jws.rstrip().lstrip() signed_token = JWS(my_jws) # create aplain old JWT so we can fish out the 'iss' t = JWT() unpacked = t.unpack(token=my_jws) payload = unpacked.payload() if "iss" not in payload: print("Missing 'iss' claim in the JWS payload.") exit(1) else: iss = payload['iss'] # Fetch the public key from iss url = "https://%s/.well-known/poet.jwk" % (iss) r = requests.get(url) if r.status_code != 200: print("The key could not be fetched.") exit(1) # load the JWK into an RSA Key structure rsak = RSAKey(**r.json()) try: vt = signed_token.verify_compact(signed_token.msg, keys=[rsak]) retval = vt except BadSignature: retval = {"error": "The signature did not match"} except NoSuitableSigningKeys: retval = {"error": str(sys.exc_info()[1])} except DeSerializationNotPossible: retval = {"error": str(sys.exc_info()[1])} except: retval = {"error": str(sys.exc_info())} return retval
def verify_signed_id_token(token, key=None, jwks=None): jwt = JWT().unpack(token) payload = jwt.payload() issuer = payload['iss'] provider_keys = None if jwt.headers['alg'].startswith('HS') and not key: raise IDTokenVerificationError( 'No symmetric key provided for signature using \'{}\' algorithm.'.format( jwt.headers['alg'])) if key: provider_keys = _create_symmetric_key(issuer, key) elif jwks: provider_keys = _parse_provider_keys_from_jwks(issuer, jwks) elif jwt.headers['alg'] != 'none': # don't fetch keys for unsigned JWT provider_keys = _fetch_provider_keys(issuer) try: return IdToken().from_jwt(token, keyjar=provider_keys).to_json() except (BadSignature, NoSuitableSigningKeys) as e: raise IDTokenVerificationError( 'No key that could be used to verify the signature could be found.')
def test_client_secret_jwt(self, client): client.token_endpoint = "https://example.com/token" client.provider_info = {'issuer': 'https://example.com/', 'token_endpoint': "https://example.com/token"} csj = ClientSecretJWT(client) cis = AccessTokenRequest() csj.construct(cis, algorithm="HS256", authn_endpoint='userinfo') assert cis["client_assertion_type"] == JWT_BEARER assert "client_assertion" in cis cas = cis["client_assertion"] _jwt = JWT().unpack(cas) jso = _jwt.payload() assert _eq(jso.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"]) assert _jwt.headers == {'alg': 'HS256'} _rj = JWS() info = _rj.verify_compact( cas, [SYMKey(k=b64e(as_bytes(client.client_secret)))]) assert _eq(info.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"]) assert info['aud'] == [client.provider_info['issuer']]
def from_jwt(self, txt, key=None, verify=True, keyjar=None, **kwargs): """ Given a signed and/or encrypted JWT, verify its correctness and then create a class instance from the content. :param txt: The JWT :param key: keys that might be used to decrypt and/or verify the signature of the JWT :param verify: Whether the signature should be verified or not :param keyjar: A KeyJar that might contain the necessary key. :param kwargs: Extra key word arguments :return: A class instance """ if key is None and keyjar is not None: key = keyjar.get_verify_key(owner="") elif key is None: key = [] if keyjar is not None and "sender" in kwargs: key.extend(keyjar.get_verify_key(owner=kwargs["sender"])) _jw = jwe.factory(txt) if _jw: if "algs" in kwargs and "encalg" in kwargs["algs"]: try: assert kwargs["algs"]["encalg"] == _jw["alg"] except AssertionError: raise WrongEncryptionAlgorithm("%s != %s" % ( _jw["alg"], kwargs["algs"]["encalg"])) try: assert kwargs["algs"]["encenc"] == _jw["enc"] except AssertionError: raise WrongEncryptionAlgorithm("%s != %s" % ( _jw["enc"], kwargs["algs"]["encenc"])) if keyjar: dkeys = keyjar.get_decrypt_key(owner="") elif key: dkeys = key else: dkeys = [] txt = _jw.decrypt(txt, dkeys) self.jwe_header = _jw.jwt.headers _jw = jws.factory(txt) if _jw: if "algs" in kwargs and "sign" in kwargs["algs"]: _alg = _jw.jwt.headers["alg"] try: assert kwargs["algs"]["sign"] == _alg except AssertionError: raise WrongSigningAlgorithm("%s != %s" % ( _alg, kwargs["algs"]["sign"])) try: _jwt = JWT().unpack(txt) jso = _jwt.payload() _header = _jwt.headers logger.debug("Raw JSON: {}".format(jso)) logger.debug("header: {}".format(_header)) if _header["alg"] == "none": pass else: if keyjar: logger.debug("Issuer keys: {}".format(keyjar.keys())) try: _iss = jso["iss"] except KeyError: pass else: if "jku" in _header: if not keyjar.find(_header["jku"], _iss): # This is really questionable try: if kwargs["trusting"]: keyjar.add(jso["iss"], _header["jku"]) except KeyError: pass if "kid" in _header and _header["kid"]: _jw["kid"] = _header["kid"] try: _key = keyjar.get_key_by_kid(_header["kid"], _iss) if _key: key.append(_key) except KeyError: pass try: self._add_key(keyjar, kwargs["opponent_id"], key) except KeyError: pass if verify: if keyjar: for ent in ["iss", "aud", "client_id"]: if ent not in jso: continue if ent == "aud": # list or basestring if isinstance(jso["aud"], six.string_types): _aud = [jso["aud"]] else: _aud = jso["aud"] for _e in _aud: self._add_key(keyjar, _e, key) else: self._add_key(keyjar, jso[ent], key) if "alg" in _header and _header["alg"] != "none": if not key: raise MissingSigningKey( "alg=%s" % _header["alg"]) logger.debug("Verify keys: {}".format(key)) _jw.verify_compact(txt, key) except Exception: raise else: self.jws_header = _jwt.headers else: jso = json.loads(txt) return self.from_dict(jso)
def test_pack_with_headers(): _jwt = JWT() jwt = _jwt.pack(parts=["", ""], headers={"foo": "bar"}) assert JWT().unpack(jwt).headers["foo"] == "bar"
# The JWS class can not work directly with rsa keys. # In this case the rsa key is wrapped in a RSAKey keys = [RSAKey(key=import_rsa_key_from_file("foo"))] _jws = JWS(payload, alg="RS512") _jwt = _jws.sign_compact(keys) print("Signed jwt:", _jwt) print() # The JWT class can be used to peek into a JWT, whether is is signed or # encrypted. It will not do any verificiation or decryption just unpacking # the JWT. jwt = JWT() jwt.unpack(_jwt) print("jwt headers:", jwt.headers) # Part 0 is the headers # Part 1 is the payload message print("jwt part 1:", jwt.part[1]) print() # If you want to verify the signature you have to use the JWS class _rj = JWS() # If everything is OK the verify_compact method will return the payload message info = _rj.verify_compact(_jwt, keys) print("Verified info:", info)
def from_jwt(self, txt, key=None, verify=True, keyjar=None, **kwargs): """ Given a signed and/or encrypted JWT, verify its correctness and then create a class instance from the content. :param txt: The JWT :param key: keys that might be used to decrypt and/or verify the signature of the JWT :param verify: Whether the signature should be verified or not :param keyjar: A KeyJar that might contain the necessary key. :param kwargs: Extra key word arguments :return: A class instance """ if key is None and keyjar is not None: key = keyjar.get_verify_key(owner="") elif key is None: key = [] if keyjar is not None and "sender" in kwargs: key.extend(keyjar.get_verify_key(owner=kwargs["sender"])) _jw = jwe.factory(txt) if _jw: if "algs" in kwargs and "encalg" in kwargs["algs"]: try: assert kwargs["algs"]["encalg"] == _jw["alg"] except AssertionError: raise WrongEncryptionAlgorithm("%s != %s" % ( _jw["alg"], kwargs["algs"]["encalg"])) try: assert kwargs["algs"]["encenc"] == _jw["enc"] except AssertionError: raise WrongEncryptionAlgorithm("%s != %s" % ( _jw["enc"], kwargs["algs"]["encenc"])) if keyjar: dkeys = keyjar.get_decrypt_key(owner="") elif key: dkeys = key else: dkeys = [] txt = as_unicode(_jw.decrypt(txt, dkeys)) self.jwe_header = _jw.jwt.headers _jw = jws.factory(txt) if _jw: if "algs" in kwargs and "sign" in kwargs["algs"]: _alg = _jw.jwt.headers["alg"] try: assert kwargs["algs"]["sign"] == _alg except AssertionError: raise WrongSigningAlgorithm("%s != %s" % ( _alg, kwargs["algs"]["sign"])) try: _jwt = JWT().unpack(txt) jso = _jwt.payload() _header = _jwt.headers logger.debug("Raw JSON: {}".format(jso)) logger.debug("header: {}".format(_header)) if _header["alg"] == "none": pass elif verify: if keyjar: key = self.get_verify_keys(keyjar, key, jso, _header, _jw, **kwargs) if "alg" in _header and _header["alg"] != "none": if not key: raise MissingSigningKey( "alg=%s" % _header["alg"]) logger.debug("Verify keys: {}".format(key)) try: _jw.verify_compact(txt, key) except NoSuitableSigningKeys: if keyjar: update_keyjar(keyjar) key = self.get_verify_keys(keyjar, key, jso, _header, _jw, **kwargs) _jw.verify_compact(txt, key) except Exception: raise else: self.jws_header = _jwt.headers else: jso = json.loads(txt) return self.from_dict(jso)
# $ ssh-keygen -t rsa -b 4096 # and provide the foo filename with requested. # # Now a JWS can be created as follow: # - retrieve the rsa key (the example below will also print it in the JWK section) # - use the JWS object to create the token specifying the algorithm to be used for signing # - call the method sign_compact providing an array of keys (eventually containing 1 key only) to be used for signing # - the example belows shows the content of the JWT, by printing it # - the signature can be verified with the method verify_compact (of course providing the same keys used for signing) payload = {"iss": "jow", "exp": 1300819380, "http://example.com/is_root": True} keys = [RSAKey(key=import_rsa_key_from_file("foo"))] jws = JWS(payload, alg="RS512").sign_compact(keys) print "jwt signed:", jws print ######################################## jwt_received = JWT() jwt_received.unpack(jws) print "jwt headers:", jwt_received.headers print "jwt part 1:", jwt_received.part[1] print _rj = JWS() info = _rj.verify_compact(jws, keys) print "Verified info:", info