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 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_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 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_with_jti(): _kj = KeyJar() _kj.add_symmetric(ALICE, "hemligt ordsprak", usage=["sig"]) alice = JWT(key_jar=_kj, iss=ALICE, sign_alg="HS256") alice.with_jti = True payload = {"sub": "sub2"} _jwt = alice.pack(payload=payload) bob = JWT(key_jar=_kj, iss=BOB, sign_alg="HS256") info = bob.unpack(_jwt) assert "jti" in info
def test_with_jti(): _kj = KeyJar() _kj.add_symmetric(ALICE, 'hemligt ordsprak', usage=['sig']) alice = JWT(key_jar=_kj, iss=ALICE, sign_alg="HS256") alice.with_jti = True payload = {'sub': 'sub2'} _jwt = alice.pack(payload=payload) bob = JWT(key_jar=_kj, iss=BOB, sign_alg="HS256") info = bob.unpack(_jwt) assert 'jti' in info
def test_client_secret_jwt(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") _jwt.with_jti = True _assertion = _jwt.pack({"aud": [CONF["issuer"]]}) request = {"client_assertion": _assertion, "client_assertion_type": JWT_BEARER} assert self.method.is_usable(request=request) authn_info = self.method.verify(request) assert authn_info["client_id"] == client_id assert "jwt" in authn_info
def test_private_key_jwt(self): # 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": [CONF["issuer"]]}) request = {"client_assertion": _assertion, "client_assertion_type": JWT_BEARER} assert self.method.is_usable(request=request) authn_info = self.method.verify(request=request) assert authn_info["client_id"] == client_id assert "jwt" in authn_info
def do_back_channel_logout(self, cinfo, sub, sid): """ :param cinfo: Client information :param sub: Subject identifier :param sid: The Issuer ID :return: Tuple with logout URI and signed logout token """ _cntx = self.endpoint_context try: back_channel_logout_uri = cinfo["backchannel_logout_uri"] except KeyError: return None # always include sub and sid so I don't check for # backchannel_logout_session_required payload = { "sub": sub, "sid": sid, "events": { BACK_CHANNEL_LOGOUT_EVENT: {} } } try: alg = cinfo["id_token_signed_response_alg"] except KeyError: alg = _cntx.provider_info["id_token_signing_alg_values_supported"][ 0] _jws = JWT(_cntx.keyjar, iss=_cntx.issuer, lifetime=86400, sign_alg=alg) _jws.with_jti = True sjwt = _jws.pack(payload=payload, recv=cinfo["client_id"]) return back_channel_logout_uri, sjwt
def test_private_key_jwt_reusage_other_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", "token").full_path]}) request = { "client_assertion": _assertion, "client_assertion_type": JWT_BEARER } # This should be OK assert self.method.is_usable(request=request) self.method.verify(request=request, endpoint=self.method.server_get( "endpoint", "token")) # This should NOT be OK with pytest.raises(NotForMe): self.method.verify(request, endpoint=self.method.server_get( "endpoint", "authorization")) # This should NOT be OK because this is the second time the token appears with pytest.raises(MultipleUsage): self.method.verify(request, endpoint=self.method.server_get( "endpoint", "token"))
def test_private_key_jwt_auth_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["authorization"].full_path]}) request = { "client_assertion": _assertion, "client_assertion_type": JWT_BEARER } authn_info = PrivateKeyJWT(endpoint_context).verify( request, endpoint="authorization") assert authn_info["client_id"] == client_id assert "jwt" in authn_info