def test_client_claims_with_default(self): session_info = { "authn_req": AREQN, "sub": "sub", "authn_event": { "authn_info": "loa2", "authn_time": time.time(), "uid": "diana" }, } self.endpoint_context.cdb["client_1"]['id_token_claims'] = { "address": None } self.endpoint_context.idtoken.kwargs['default_claims'] = { "nickname": { "essential": True } } self.endpoint_context.idtoken.enable_claims_per_client = True req = {"client_id": "client_1"} _token = self.endpoint_context.idtoken.make(req, session_info) assert _token client_keyjar = KeyJar() _jwks = self.endpoint_context.keyjar.export_jwks() client_keyjar.import_jwks(_jwks, self.endpoint_context.issuer) _jwt = JWT(key_jar=client_keyjar, iss="client_1") res = _jwt.unpack(_token) assert "address" in res assert "nickname" in res
def test_unpack_aggregated_response_missing_keys(self): claims = { "address": { "street_address": "1234 Hollywood Blvd.", "locality": "Los Angeles", "region": "CA", "postal_code": "90210", "country": "US" }, "phone_number": "+1 (555) 123-4567" } _keyjar = build_keyjar(KEYSPEC) srv = JWT(_keyjar, iss=ISS, sign_alg='ES256') _jwt = srv.pack(payload=claims) resp = OpenIDSchema(sub='diana', given_name='Diana', family_name='krall', _claim_names={ 'address': 'src1', 'phone_number': 'src1' }, _claim_sources={'src1': {'JWT': _jwt}}) _resp = self.service.parse_response(resp.to_json(), state='abcde') assert _resp
def test_sign_encrypt_id_token(): client_info = RegistrationResponse(id_token_signed_response_alg='RS512', client_id='client_1') session_info = { 'authn_req': AREQN, 'sub': 'sub', 'authn_event': { "authn_info": 'loa2', "authn_time": time.time() } } ENDPOINT_CONTEXT.jwx_def["signing_alg"] = {'id_token': 'RS384'} ENDPOINT_CONTEXT.cdb['client_1'] = client_info.to_dict() _token = sign_encrypt_id_token(ENDPOINT_CONTEXT, session_info, 'client_1', sign=True) assert _token _jws = jws.factory(_token) assert _jws.jwt.headers['alg'] == 'RS512' client_keyjar = KeyJar() _jwks = KEYJAR.export_jwks() client_keyjar.import_jwks(_jwks, ENDPOINT_CONTEXT.issuer) _jwt = JWT(key_jar=client_keyjar, iss='client_1') res = _jwt.unpack(_token) assert isinstance(res, dict) assert res['aud'] == ['client_1']
def test_construct(self, entity): token_service = entity.client_get("service", 'accesstoken') kb_rsa = KeyBundle(source='file://{}'.format( os.path.join(BASE_PATH, "data/keys/rsa.key")), fileformat='der') for key in kb_rsa: key.add_kid() _context = token_service.client_get("service_context") _context.keyjar.add_kb('', kb_rsa) _context.provider_info = { 'issuer': 'https://example.com/', 'token_endpoint': "https://example.com/token" } _context.registration_response = { 'token_endpoint_auth_signing_alg': 'RS256' } token_service.endpoint = "https://example.com/token" request = AccessTokenRequest() pkj = PrivateKeyJWT() http_args = pkj.construct(request, service=token_service, authn_endpoint='token_endpoint') assert http_args == {} cas = request["client_assertion"] _kj = KeyJar() _kj.add_kb(_context.client_id, kb_rsa) jso = JWT(key_jar=_kj).unpack(cas) assert _eq(jso.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"]) # assert _jwt.headers == {'alg': 'RS256'} assert jso['aud'] == [_context.provider_info['token_endpoint']]
def test_sign_encrypt_id_token(self): client_info = RegistrationResponse( id_token_signed_response_alg="RS512", client_id="client_1") session_info = { "authn_req": AREQN, "sub": "sub", "authn_event": { "authn_info": "loa2", "authn_time": time.time() }, } self.endpoint_context.jwx_def["signing_alg"] = {"id_token": "RS384"} self.endpoint_context.cdb["client_1"] = client_info.to_dict() _token = self.endpoint_context.idtoken.sign_encrypt(session_info, "client_1", sign=True) assert _token _jws = jws.factory(_token) assert _jws.jwt.headers["alg"] == "RS512" client_keyjar = KeyJar() _jwks = self.endpoint_context.keyjar.export_jwks() client_keyjar.import_jwks(_jwks, self.endpoint_context.issuer) _jwt = JWT(key_jar=client_keyjar, iss="client_1") res = _jwt.unpack(_token) assert isinstance(res, dict) assert res["aud"] == ["client_1"]
def verify(self, request, **kwargs): _jwt = JWT(self.endpoint_context.keyjar) try: ca_jwt = _jwt.unpack(request["client_assertion"]) except (Invalid, MissingKey, BadSignature) as err: logger.info("%s" % sanitize(err)) raise AuthnFailure("Could not verify client_assertion.") try: logger.debug("authntoken: %s" % sanitize(ca_jwt.to_dict())) except AttributeError: logger.debug("authntoken: %s" % sanitize(ca_jwt)) request[verified_claim_name("client_assertion")] = ca_jwt try: client_id = kwargs["client_id"] except KeyError: client_id = ca_jwt["iss"] # I should be among the audience # could be either my issuer id or the token endpoint if self.endpoint_context.issuer in ca_jwt["aud"]: pass elif self.endpoint_context.endpoint["token"].full_path in ca_jwt[ "aud"]: pass else: raise NotForMe("Not for me!") return {"client_id": client_id, "jwt": ca_jwt}
def test_construct(self, services): _service = services['accesstoken'] kb_rsa = KeyBundle(source='file://{}'.format( os.path.join(BASE_PATH, "data/keys/rsa.key")), fileformat='der') for key in kb_rsa: key.add_kid() _service.service_context.keyjar.add_kb('', kb_rsa) _service.service_context.set( 'provider_info', { 'issuer': 'https://example.com/', 'token_endpoint': "https://example.com/token" }) services['accesstoken'].endpoint = "https://example.com/token" request = AccessTokenRequest() pkj = PrivateKeyJWT() http_args = pkj.construct(request, service=_service, algorithm="RS256", authn_endpoint='token_endpoint') assert http_args == {} cas = request["client_assertion"] _kj = KeyJar() _kj.add_kb(_service.service_context.get('client_id'), kb_rsa) jso = JWT(key_jar=_kj).unpack(cas) assert _eq(jso.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"]) # assert _jwt.headers == {'alg': 'RS256'} assert jso['aud'] == [ _service.service_context.get('provider_info')['token_endpoint'] ]
def test_private_key_jwt_auth_endpoint(self): # Own dynamic keys client_keyjar = build_keyjar(KEYDEFS) # The servers keys client_keyjar.import_jwks(KEYJAR.export_jwks(private=True), CONF["issuer"]) _jwks = client_keyjar.export_jwks() self.method.server_get("endpoint_context").keyjar.import_jwks( _jwks, client_id) _jwt = JWT(client_keyjar, iss=client_id, sign_alg="RS256") _jwt.with_jti = True _assertion = _jwt.pack({ "aud": [self.method.server_get("endpoint", "authorization").full_path] }) request = { "client_assertion": _assertion, "client_assertion_type": JWT_BEARER } assert self.method.is_usable(request=request) authn_info = self.method.verify( request=request, endpoint=self.method.server_get("endpoint", "authorization"), ) assert authn_info["client_id"] == client_id assert "jwt" in authn_info
def test_verify_client_jws_authn_method(self): client_keyjar = KeyJar() client_keyjar.import_jwks(KEYJAR.export_jwks(private=True), CONF["issuer"]) # The only own key the client has a this point client_keyjar.add_symmetric("", client_secret, ["sig"]) _jwt = JWT(client_keyjar, iss=client_id, sign_alg="HS256") # Audience is OP issuer ID aud = "{}token".format(CONF["issuer"]) # aud == Token endpoint _assertion = _jwt.pack({"aud": [aud]}) request = { "client_assertion": _assertion, "client_assertion_type": JWT_BEARER } http_info = {"headers": {}} res = verify_client( self.endpoint_context, request, http_info=http_info, endpoint=self.server.server_get("endpoint", "token"), ) assert res["method"] == "client_secret_jwt" assert res["client_id"] == "client_id"
def test_private_key_jwt_reusage_other_endpoint(): # Own dynamic keys client_keyjar = build_keyjar(KEYDEFS) # The servers keys client_keyjar[conf["issuer"]] = KEYJAR.issuer_keys[""] _jwks = client_keyjar.export_jwks() endpoint_context.keyjar.import_jwks(_jwks, client_id) _jwt = JWT(client_keyjar, iss=client_id, sign_alg="RS256") _jwt.with_jti = True _assertion = _jwt.pack( {"aud": [endpoint_context.endpoint["token"].full_path]}) request = { "client_assertion": _assertion, "client_assertion_type": JWT_BEARER } # This should be OK PrivateKeyJWT(endpoint_context).verify(request, endpoint="token") # This should NOT be OK with pytest.raises(NotForMe): PrivateKeyJWT(endpoint_context).verify(request, endpoint="authorization") # This should NOT be OK with pytest.raises(MultipleUsage): PrivateKeyJWT(endpoint_context).verify(request, endpoint="token")
def make_openid_request(arq, keys, issuer, request_object_signing_alg, recv, with_jti=False, lifetime=0): """ Construct the JWT to be passed by value (the request parameter) or by reference (request_uri). The request will be signed :param arq: The Authorization request :param keys: Keys to use for signing/encrypting. A KeyJar instance :param issuer: Who is signing this JSON Web Token :param request_object_signing_alg: Which signing algorithm to use :param recv: The intended receiver of the request :param with_jti: Whether a JTI should be included in the JWT. :param lifetime: How long the JWT is expect to be live. :return: JWT encoded OpenID request """ _jwt = JWT(key_jar=keys, iss=issuer, sign_alg=request_object_signing_alg) if with_jti: _jwt.with_jti = True if lifetime: _jwt.lifetime = lifetime return _jwt.pack(arq.to_dict(), owner=issuer, recv=recv)
def do_back_channel_logout(self, cinfo, sid): """ :param cinfo: Client information :param sid: The session ID :return: Tuple with logout URI and signed logout token """ _context = self.server_get("endpoint_context") try: back_channel_logout_uri = cinfo["backchannel_logout_uri"] except KeyError: return None # Create the logout token # always include sub and sid so I don't check for # backchannel_logout_session_required enc_msg = self._encrypt_sid(sid) payload = {"sid": enc_msg, "events": {BACK_CHANNEL_LOGOUT_EVENT: {}}} try: alg = cinfo["id_token_signed_response_alg"] except KeyError: alg = _context.provider_info["id_token_signing_alg_values_supported"][0] _jws = JWT(_context.keyjar, iss=_context.issuer, lifetime=86400, sign_alg=alg) _jws.with_jti = True _logout_token = _jws.pack(payload=payload, recv=cinfo["client_id"]) return back_channel_logout_uri, _logout_token
def test_client_secret_jwt(self, client): _ci = client.client_info _ci.token_endpoint = "https://example.com/token" _ci.provider_info = { 'issuer': 'https://example.com/', 'token_endpoint': "https://example.com/token" } csj = ClientSecretJWT() request = AccessTokenRequest() csj.construct(request, cli_info=client.client_info, algorithm="HS256", authn_endpoint='userinfo') assert request["client_assertion_type"] == JWT_BEARER assert "client_assertion" in request cas = request["client_assertion"] _skey = [SYMKey(k=b64e(as_bytes(_ci.client_secret)), use='sig')] jso = JWT(rec_keys={client.client_id: _skey}).unpack(cas) assert _eq(jso.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"]) _rj = JWS() info = _rj.verify_compact( cas, [SYMKey(k=b64e(as_bytes(_ci.client_secret)))]) assert _eq(info.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"]) assert info['aud'] == [_ci.provider_info['issuer']]
def test_client_secret_jwt(self, services): _service_context = services['accesstoken'].service_context _service_context.token_endpoint = "https://example.com/token" _service_context.set( 'provider_info', { 'issuer': 'https://example.com/', 'token_endpoint': "https://example.com/token" }) csj = ClientSecretJWT() request = AccessTokenRequest() csj.construct(request, service=services['accesstoken'], algorithm="HS256", authn_endpoint='userinfo') assert request["client_assertion_type"] == JWT_BEARER assert "client_assertion" in request cas = request["client_assertion"] _kj = KeyJar() _kj.add_symmetric(_service_context.get('client_id'), _service_context.get('client_secret'), usage=['sig']) jso = JWT(key_jar=_kj, sign_alg='HS256').unpack(cas) assert _eq(jso.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"]) _rj = JWS(alg='HS256') info = _rj.verify_compact( cas, _kj.get_signing_key(issuer_id=_service_context.get('client_id'))) assert _eq(info.keys(), ["aud", "iss", "sub", "jti", "exp", "iat"]) assert info['aud'] == [_service_context.get('provider_info')['issuer']]
class Challenger(object): def __init__(self, kb: KeyBundle, issuer: str, lifetime: int) -> None: self.logger = logging.getLogger(__name__).getChild( self.__class__.__name__) self.issuer = issuer self.kj = KeyJar() self.kj.add_kb(self.issuer, kb) sign_alg = None enc_alg = None enc_enc = None kid = None for key in self.kj.get(key_use="enc", issuer_id=issuer): kid = key.kid if key.kty == "oct": sign_alg = "HS256" enc_alg = None enc_enc = None break elif key.kty == "EC": sign_alg = "ES256" enc_alg = "ECDH-ES" enc_enc = "A128GCM" break elif key.kty == "RSA": sign_alg = "RS256" enc_alg = "RSA1_5" enc_enc = "A128GCM" break if kid is None: raise Exception("No challenge key found") sign = sign_alg is not None encrypt = enc_alg is not None self.logger.info("Using challenge key kid=%s sign=%s encrypt=%s", kid, sign, encrypt) self.jwt = JWT( key_jar=self.kj, iss=self.issuer, lifetime=lifetime, sign=sign, sign_alg=sign_alg, encrypt=encrypt, enc_alg=enc_alg, enc_enc=enc_enc, ) def issue_bytes(self, payload: dict) -> bytes: """Issue token challenge""" return str(self.jwt.pack(payload=payload, recv=self.issuer)).encode() def verify_bytes(self, challenge: bytes) -> dict: """Verify challenge and return payload""" token = challenge.decode() payload = self.jwt.unpack(token) now = time.time() if "nbf" in payload and now < int(payload.get("nbf")): raise BadSignature("Token not yet valid (t < nbf)") if "exp" in payload and now >= int(payload.get("exp")): raise BadSignature("Token expired (t >= exp)") return dict(payload)
class EncryptedJWTFactory(EncryptedTokenFactory): key_jar: KeyJar def __init__(self, key_jar: KeyJar = None, encrypt: bool = True, sign: bool = True, **kwargs): if encrypt is not True: raise RuntimeError('JWT encryption is mandatory.') self.key_jar = key_jar if key_jar is not None else KeyJar() self._jwt = JWT(key_jar=self.key_jar, encrypt=encrypt, sign=sign, **kwargs) @property def issuer_id(self): return self._jwt.iss @classmethod def new_keys(cls, iss: str = 'Generic', **kwargs): """Creates a new key jar based on RSA keys. """ uses = ['enc', 'sig'] if kwargs.get('sign', True) else ['enc'] key_specs = [{"type": "RSA", "use": uses}] key_jar = build_keyjar(key_specs, issuer_id=iss) return cls(key_jar, iss=iss, **kwargs) def generate(self, payload: dict, subject: str = 'token', recv: typing.Optional[str] = None) -> str: if recv is None: recv = self._jwt.iss token = self._jwt.pack( recv=recv, payload={ "sub": subject, "data": payload }, encrypt=True, ) return token def decrypt(self, token: str) -> dict: info = self._jwt.unpack(token) if self._jwt.lifetime: now = utc_time_sans_frac() if 'iat' not in info or 'exp' not in info: raise MissingExpirationHeader() if now < info['iat']: raise NotYet() if now > info['exp']: raise Expired() return info.get('data')
def _do_jwt(self, info): args = {'allowed_sign_algs': self.service_context.get_sign_alg(self.service_name)} enc_algs = self.service_context.get_enc_alg_enc(self.service_name) args['allowed_enc_algs'] = enc_algs['alg'] args['allowed_enc_encs'] = enc_algs['enc'] _jwt = JWT(key_jar=self.service_context.keyjar, **args) _jwt.iss = self.service_context.get('client_id') return _jwt.unpack(info)
def do_response(self, response_args=None, request=None, client_id="", **kwargs): if "error" in kwargs and kwargs["error"]: return Endpoint.do_response(self, response_args, request, **kwargs) _context = self.endpoint_context if not client_id: raise MissingValue("client_id") # Should I return a JSON or a JWT ? _cinfo = _context.cdb[client_id] # default is not to sign or encrypt try: sign_alg = _cinfo["userinfo_signed_response_alg"] sign = True except KeyError: sign_alg = "" sign = False try: enc_enc = _cinfo["userinfo_encrypted_response_enc"] enc_alg = _cinfo["userinfo_encrypted_response_alg"] encrypt = True except KeyError: encrypt = False enc_alg = enc_enc = "" if encrypt or sign: _jwt = JWT( self.endpoint_context.keyjar, iss=self.endpoint_context.issuer, sign=sign, sign_alg=sign_alg, encrypt=encrypt, enc_enc=enc_enc, enc_alg=enc_alg, ) resp = _jwt.pack(response_args, recv=client_id) content_type = "application/jwt" else: if isinstance(response_args, dict): resp = json.dumps(response_args) else: resp = response_args.to_json() content_type = "application/json" http_headers = [("Content-type", content_type)] http_headers.extend(OAUTH2_NOCACHE_HEADERS) return {"response": resp, "http_headers": http_headers}
def sign_encrypt( self, session_info, client_id, code=None, access_token=None, user_info=None, sign=True, encrypt=False, lifetime=None, extra_claims=None, ): """ Signed and or encrypt a IDToken :param session_info: Session information :param client_id: Client ID :param code: Access grant :param access_token: Access Token :param user_info: User information :param sign: If the JWT should be signed :param encrypt: If the JWT should be encrypted :param extra_claims: Extra claims to be added to the ID Token :return: IDToken as a signed and/or encrypted JWT """ _cntx = self.endpoint_context client_info = _cntx.cdb[client_id] alg_dict = get_sign_and_encrypt_algorithms(_cntx, client_info, "id_token", sign=sign, encrypt=encrypt) _authn_event = session_info["authn_event"] _idt_info = self.payload( session_info, acr=_authn_event["authn_info"], alg=alg_dict["sign_alg"], code=code, access_token=access_token, user_info=user_info, auth_time=_authn_event["authn_time"], lifetime=lifetime, extra_claims=extra_claims, ) _jwt = JWT(_cntx.keyjar, iss=_cntx.issuer, lifetime=_idt_info["lifetime"], **alg_dict) return _jwt.pack(_idt_info["payload"], recv=client_id)
def create_entity_statement(iss, sub, key_jar, metadata=None, metadata_policy=None, authority_hints=None, lifetime=86400, aud='', include_jwks=True, constraints=None, **kwargs): """ :param iss: The issuer of the signed JSON Web Token :param sub: The subject which the metadata describes :param key_jar: A KeyJar instance :param metadata: The entity's metadata organised as a dictionary with the entity type as key :param metadata_policy: Metadata policy :param authority_hints: A dictionary with immediate superiors in the trust chains as keys and lists of identifier of trust roots as values. :param lifetime: The life time of the signed JWT. :param aud: Possible audience for the JWT :param include_jwks: Add JWKS :param constraints: A dictionary with constraints. :return: A signed JSON Web Token """ msg = {'sub': sub} if metadata: msg['metadata'] = metadata if metadata_policy: msg['metadata_policy'] = metadata_policy if authority_hints: msg['authority_hints'] = authority_hints if aud: msg['aud'] = aud if constraints: msg['constraints'] = constraints if kwargs: msg.update(kwargs) if include_jwks: # The public signing keys of the subject msg['jwks'] = key_jar.export_jwks(issuer_id=sub) packer = JWT(key_jar=key_jar, iss=iss, lifetime=lifetime) return packer.pack(payload=msg)
def verify_signed_bundle(signed_bundle, ver_keys): """ Verify the signature of a signed JWT. :param signed_bundle: A signed JWT where the body is a JWKS bundle :param ver_keys: Keys that can be used to verify signatures of the signed_bundle. :type ver_keys: A :py:class:`oidcmsg.key_jar.KeyJar` instance :return: The bundle or None """ _jwt = JWT(ver_keys) return _jwt.unpack(signed_bundle)
def test_parse(self): session_id = setup_session( self.endpoint.endpoint_context, AUTH_REQ, uid="diana" ) _dic = self.endpoint.endpoint_context.sdb.upgrade_to_token(key=session_id) _verifier = JWT(self.endpoint.endpoint_context.keyjar) _info = _verifier.unpack(_dic["access_token"]) assert _info["ttype"] == "T" assert _info["phone_number"] == "+46907865000" assert set(_info["aud"]) == {"client_1", "https://example.org/appl"}
def verify(self, request, key_type, **kwargs): _context = self.server_get("endpoint_context") _jwt = JWT(_context.keyjar, msg_cls=JsonWebToken) try: ca_jwt = _jwt.unpack(request["client_assertion"]) except (Invalid, MissingKey, BadSignature) as err: logger.info("%s" % sanitize(err)) raise AuthnFailure("Could not verify client_assertion.") _sign_alg = ca_jwt.jws_header.get("alg") if _sign_alg and _sign_alg.startswith("HS"): if key_type == "private_key": raise AttributeError("Wrong key type") keys = _context.keyjar.get("sig", "oct", ca_jwt["iss"], ca_jwt.jws_header.get("kid")) _secret = _context.cdb[ca_jwt["iss"]].get("client_secret") if _secret and keys[0].key != as_bytes(_secret): raise AttributeError( "Oct key used for signing not client_secret") else: if key_type == "client_secret": raise AttributeError("Wrong key type") authtoken = sanitize(ca_jwt.to_dict()) logger.debug("authntoken: {}".format(authtoken)) _endpoint = kwargs.get("endpoint") if _endpoint is None or not _endpoint: if _context.issuer in ca_jwt["aud"]: pass else: raise NotForMe("Not for me!") else: if set(ca_jwt["aud"]).intersection( _endpoint.allowed_target_uris()): pass else: raise NotForMe("Not for me!") # If there is a jti use it to make sure one-time usage is true _jti = ca_jwt.get("jti") if _jti: _key = "{}:{}".format(ca_jwt["iss"], _jti) if _key in _context.jti_db: raise MultipleUsage("Have seen this token once before") else: _context.jti_db[_key] = utc_time_sans_frac() request[verified_claim_name("client_assertion")] = ca_jwt client_id = kwargs.get("client_id") or ca_jwt["iss"] return {"client_id": client_id, "jwt": ca_jwt}
def test_jws_authn_method_wrong_key(self): client_keyjar = KeyJar() client_keyjar[CONF["issuer"]] = KEYJAR.issuer_keys[""] # Fake symmetric key client_keyjar.add_symmetric("", "client_secret:client_secret", ["sig"]) _jwt = JWT(client_keyjar, iss=client_id, sign_alg="HS256") _assertion = _jwt.pack({"aud": [CONF["issuer"]]}) request = {"client_assertion": _assertion, "client_assertion_type": JWT_BEARER} with pytest.raises(NoSuitableSigningKeys): self.method.verify(request=request, key_type='private_key')
def pack(self, req, receiver='', iss='', lifetime=0, sign=True, sign_alg='', encrypt=False, enc_enc="A128CBC-HS256", enc_alg="RSA1_5", aud=None): """ :param req: Original metadata statement as a :py:class:`MetadataStatement` instance :param receiver: The immediate receiver of the JWS :param iss: :param lifetime: :param sign: :param sign_alg: :param encrypt: :param enc_alg: :param enc_enc: :param aud: The audience, a list of receivers. :return: A dictionary with a signed JWT as value with the key 'sms' """ if not iss: iss = self.iss if not lifetime: lifetime = self.lifetime keyjar = self.keyjar # Own copy _metadata = copy.deepcopy(req) if self.add_ons: _metadata.update(self.add_ons) args = {} if sign: if sign_alg: args['sign_alg'] = sign_alg else: args['sign_alg'] = self.alg if encrypt: args['enc_enc'] = enc_enc args['enc_alg'] = enc_alg _jwt = JWT(keyjar, iss=iss, msg_cls=_metadata.__class__, lifetime=lifetime, **args) # _jwt.sign_alg = self.alg if iss in keyjar.issuer_keys: owner = iss else: owner = '' return _jwt.pack(payload=_metadata.to_dict(), owner=owner, recv=receiver, aud=aud)
def sign_encrypt( self, session_id, client_id, code=None, access_token=None, sign=True, encrypt=False, lifetime=None, extra_claims=None, ) -> str: """ Signed and or encrypt a IDToken :param lifetime: How long the ID Token should be valid :param session_id: Session information :param client_id: Client ID :param code: Access grant :param access_token: Access Token :param sign: If the JWT should be signed :param encrypt: If the JWT should be encrypted :param extra_claims: Extra claims to be added to the ID Token :return: IDToken as a signed and/or encrypted JWT """ _context = self.server_get("endpoint_context") client_info = _context.cdb[client_id] alg_dict = get_sign_and_encrypt_algorithms(_context, client_info, "id_token", sign=sign, encrypt=encrypt) _payload = self.payload( session_id=session_id, alg=alg_dict["sign_alg"], code=code, access_token=access_token, extra_claims=extra_claims, ) if lifetime is None: lifetime = self.lifetime _jwt = JWT(_context.keyjar, iss=_context.issuer, lifetime=lifetime, **alg_dict) return _jwt.pack(_payload, recv=client_id)
def __init__(self, key_jar: KeyJar = None, encrypt: bool = True, sign: bool = True, **kwargs): if encrypt is not True: raise RuntimeError('JWT encryption is mandatory.') self.key_jar = key_jar if key_jar is not None else KeyJar() self._jwt = JWT(key_jar=self.key_jar, encrypt=encrypt, sign=sign, **kwargs)
def test_jws_authn_method_aud_userinfo_endpoint(self): client_keyjar = KeyJar() client_keyjar[CONF["issuer"]] = KEYJAR.issuer_keys[""] # The only own key the client has a this point client_keyjar.add_symmetric("", client_secret, ["sig"]) _jwt = JWT(client_keyjar, iss=client_id, sign_alg="HS256") # audience is the OP - not specifically the user info endpoint _assertion = _jwt.pack({"aud": [CONF["issuer"]]}) request = {"client_assertion": _assertion, "client_assertion_type": JWT_BEARER} assert self.method.verify(request=request, endpoint="userinfo", key_type='client_secret')
def test_jws_authn_method_aud_iss(self): client_keyjar = KeyJar() client_keyjar[CONF["issuer"]] = KEYJAR.issuer_keys[""] # The only own key the client has a this point client_keyjar.add_symmetric("", client_secret, ["sig"]) _jwt = JWT(client_keyjar, iss=client_id, sign_alg="HS256") # Audience is OP issuer ID aud = CONF["issuer"] _assertion = _jwt.pack({"aud": [aud]}) request = {"client_assertion": _assertion, "client_assertion_type": JWT_BEARER} assert self.method.verify(request=request, key_type='client_secret')
def create_signed_bundle(self, sign_alg='RS256', iss_list=None): """ Create a signed JWT containing a dictionary with Issuer IDs as keys and JWKSs as values. If iss_list is empty then all available issuers are included. :param sign_alg: Which algorithm to use when signing the JWT :param iss_list: A list of issuer IDs who's keys should be included in the signed bundle. :return: A signed JWT """ data = self.dict(iss_list) _jwt = JWT(self.sign_keys, iss=self.iss, sign_alg=sign_alg) return _jwt.pack({'bundle':data})