def rp_service_setup(self): entity_id = 'https://foodle.uninett.no' config = { 'client_id': entity_id, 'client_secret': 'a longesh password', 'redirect_uris': ['https://example.com/cli/authz_cb'], "keys": { "uri_path": "static/jwks.json", "key_defs": KEY_DEFS }, "client_preferences": { "grant_types": ['authorization_code', 'implicit', 'refresh_token'], "id_token_signed_response_alg": "ES256", "token_endpoint_auth_method": "client_secret_basic", "federation_type": ['automatic'] }, "federation": { "entity_id": entity_id, "keys": { "uri_path": "static/fed_jwks.json", "key_defs": KEY_DEFS }, "endpoint": { "fetch": { "path": "fetch", "class": Fetch, "kwargs": { "client_authn_method": None }, } }, "trusted_roots": ANCHOR, "authority_hints": ['https://ntnu.no'], "entity_type": 'openid_relying_party', "opponent_entity_type": 'openid_provider', } } oidc_service = DEFAULT_OIDC_SERVICES.copy() oidc_service.update(DEFAULT_OIDC_FED_SERVICES) self.entity = FederationRP(services=oidc_service, config=config) httpc = Publisher(os.path.join(BASE_PATH, 'base_data')) _context = self.entity.client_get("service_context") # The test data collector _context.federation_entity.collector = DummyCollector( trusted_roots=ANCHOR, httpd=httpc, root_dir=os.path.join(BASE_PATH, 'base_data')) self.disco_service = self.entity.client_get("service", 'provider_info') self.registration_service = self.entity.client_get( "service", 'registration')
def create_endpoint(self): # First the RP _config = copy.deepcopy(RP_CONFIG) _config['behaviour'] = {'federation_types_supported': ['explicit']} entity = FederationRP(config=_config) self.rp_federation_entity = entity.client_get( "service_context").federation_entity # The test data collector self.rp_federation_entity.collector = DummyCollector( trusted_roots=ANCHOR, httpd=HTTPC, root_dir=os.path.join(BASE_PATH, 'base_data')) # The RP has/supports 3 services self.service = { 'discovery': FedProviderInfoDiscovery(entity.client_get), 'registration': Registration(entity.client_get), 'authorization': FedAuthorization(entity.client_get, conf={"request_object_expires_in": 300}), } # and now for the OP _config = copy.copy(OP_CONF) _config['add_on'] = { "automatic_registration": { "function": "fedservice.op.add_on.automatic_registration.add_support", "kwargs": { "new_id": False, # default False 'client_registration_authn_methods_supported': { "ar": ['request_object'] }, 'where': ['authorization'] } } } server = FederationServer(_config) self.registration_endpoint = server.server_get("endpoint", "registration") self.authorization_endpoint = server.server_get( "endpoint", "authorization") self.provider_endpoint = server.server_get("endpoint", "provider_config") federation_entity = server.server_get( "endpoint_context").federation_entity federation_entity.collector = DummyCollector(httpd=Publisher(ROOT_DIR), trusted_roots=ANCHOR, root_dir=ROOT_DIR)
def rp_service_setup(self): entity_id = 'https://foodle.uninett.no' config = { 'redirect_uris': ['https://example.com/cli/authz_cb'], "keys": { "uri_path": "static/jwks.json", "key_defs": KEY_DEFS }, "client_preferences": { "grant_types": ['authorization_code', 'implicit', 'refresh_token'], "id_token_signed_response_alg": "ES256", "token_endpoint_auth_method": "client_secret_basic", "federation_type": ['automatic'] }, "services": { 'authorization': { 'class': 'oidcrp.oidc.authorization.Authorization' }, 'access_token': { 'class': 'oidcrp.oidc.access_token.AccessToken' } }, "federation": { "entity_id": entity_id, "keys": { "uri_path": "static/fed_jwks.json", "key_defs": KEY_DEFS }, "endpoint": { "fetch": { "path": "fetch", "class": Fetch, "kwargs": { "client_authn_method": None }, } }, "trusted_roots": ANCHOR, "authority_hints": ['https://ntnu.no'], "entity_type": 'openid_relying_party', "opponent_entity_type": 'openid_provider', } } oidc_service = DEFAULT_OIDC_SERVICES.copy() oidc_service.update(DEFAULT_OIDC_FED_SERVICES) self.entity = FederationRP(services=oidc_service, config=config) _context = self.entity.client_get("service_context") _context.provider_info = {'token_endpoint': "https://op.example.org"}
def create_endpoint(self): # First the RP _config = copy.deepcopy(RP_CONFIG) _config['behaviour'] = {'federation_types_supported': ['explicit']} entity = FederationRP(config=_config) self.rp_federation_entity = entity.client_get( "service_context").federation_entity # The test data collector self.rp_federation_entity.collector = DummyCollector( trusted_roots=ANCHOR, httpd=HTTPC, root_dir=os.path.join(BASE_PATH, 'base_data')) entity._service = { 'discovery': FedProviderInfoDiscovery(entity.client_get), 'registration': Registration(entity.client_get), 'authorization': FedAuthorization(entity.client_get, conf={"request_object_expires_in": 300}), } self.rp = entity # and now for the OP _config = copy.copy(OP_CONF) server = FederationServer(_config) self.registration_endpoint = server.server_get("endpoint", "registration") self.authorization_endpoint = server.server_get( "endpoint", "authorization") self.provider_endpoint = server.server_get("endpoint", "provider_config") federation_entity = server.server_get( "endpoint_context").federation_entity federation_entity.collector = DummyCollector(httpd=Publisher(ROOT_DIR), trusted_roots=ANCHOR, root_dir=ROOT_DIR)
def create_endpoint(self): # First the RP entity = FederationRP(config=RP_CONFIG) _fe = entity.client_get("service_context").federation_entity # The test data collector _fe.collector = DummyCollector(trusted_roots=ANCHOR, httpd=HTTPC, root_dir=os.path.join( BASE_PATH, 'base_data')) # The RP has/supports 3 services self.service = { 'discovery': FedProviderInfoDiscovery(entity.client_get), 'registration': Registration(entity.client_get), 'authorization': FedAuthorization(entity.client_get), } # and now for the OP server = FederationServer(OP_CONF, httpc=HTTPC) self.registration_endpoint = server.server_get("endpoint", "registration") self.authorization_endpoint = server.server_get( "endpoint", "authorization") self.provider_endpoint = server.server_get("endpoint", "provider_config") # === Federation stuff ======= federation_entity = server.server_get( "endpoint_context").federation_entity federation_entity.collector = DummyCollector(httpd=Publisher(ROOT_DIR), trusted_roots=ANCHOR, root_dir=ROOT_DIR)
def create_setup(self): # First the RP config = { 'behaviour': { 'federation_types_supported': ['automatic'] }, 'issuer': "https://op.ntnu.no", 'keys': {'key_defs': KEYSPEC}, "federation": { "endpoint": { "fetch": { "path": "fetch", "class": Fetch, "kwargs": {"client_authn_method": None}, } }, 'entity_id': RP_ENTITY_ID, "trusted_roots": ANCHOR, "authority_hints": ['https://ntnu.no'], "entity_type": 'openid_relying_party', "opponent_entity_type": 'openid_provider' } } self.entity = FederationRP(config=config) service_context = self.entity.get_service_context() service_context.federation_entity.collector = DummyCollector( trusted_roots=ANCHOR, root_dir=ROOT_DIR) # The RP has/supports 2 services self.discovery_service = FedProviderInfoDiscovery(self.entity.client_get) self.registration_service = RPRegistration(self.entity.client_get) # self.authorization_service = FedAuthorization(entity.client_get) # and now for the OP op_entity_id = "https://op.ntnu.no" op_conf = { "issuer": op_entity_id, "password": "******", "token_handler_args": { "jwks_def": { "private_path": "private/token_jwks.json", "read_only": False, "key_defs": [ {"type": "oct", "bytes": 24, "use": ["enc"], "kid": "code"}, {"type": "oct", "bytes": 24, "use": ["enc"], "kid": "refresh"}, ], }, "code": {"lifetime": 600}, "token": { "class": "oidcop.token.jwt_token.JWTToken", "kwargs": { "lifetime": 3600, "add_claims": [ "email", "email_verified", "phone_number", "phone_number_verified", ], "add_claim_by_scope": True, "aud": ["https://example.org/appl"] }, }, "refresh": {"lifetime": 86400}, }, "claims_interface": {"class": "oidcop.session.claims.ClaimsInterface", "kwargs": {}}, "verify_ssl": False, "capabilities": CAPABILITIES, "keys": {"uri_path": "static/jwks.json", "key_defs": KEYSPEC}, "id_token": { "class": IDToken, "kwargs": { "default_claims": { "email": {"essential": True}, "email_verified": {"essential": True}, } }, }, "endpoint": { "provider_config": { "path": ".well-known/openid-configuration", "class": ProviderConfiguration, "kwargs": {}, }, "registration": { "path": "registration", "class": OPRegistration, "kwargs": {}, }, "authorization": { "path": "authorization", "class": Authorization, "kwargs": { "response_types_supported": [ " ".join(x) for x in RESPONSE_TYPES_SUPPORTED ], "response_modes_supported": ["query", "fragment", "form_post"], "claims_parameter_supported": True, "request_parameter_supported": True, "request_uri_parameter_supported": True, }, }, "pushed_authorization": { "path": "pushed_authorization", "class": PushedAuthorization, "kwargs": { "client_authn_method": [ "client_secret_post", "client_secret_basic", "client_secret_jwt", "private_key_jwt", ] }, }, }, "authentication": { "anon": { "acr": "http://www.swamid.se/policy/assurance/al1", "class": "oidcop.user_authn.user.NoAuthn", "kwargs": {"user": "******"}, } }, "template_dir": "template", "cookie_handler": { "class": CookieHandler, "kwargs": { "keys": {"key_defs": COOKIE_KEYDEFS}, "name": { "session": "oidc_op", "register": "oidc_op_reg", "session_management": "oidc_op_sman" } }, }, 'add_on': { "automatic_registration": { "function": "fedservice.op.add_on.automatic_registration.add_support", "kwargs": { "new_id": False, # default False "where": ["pushed_authorization"] } } }, "federation": { "endpoint": { "fetch": { "path": "fetch", "class": Fetch, "kwargs": {"client_authn_method": None}, } }, "entity_id": op_entity_id, "trusted_roots": ANCHOR, "authority_hints": ['https://ntnu.no'], "entity_type": 'openid_relying_party', "opponent_entity_type": 'openid_relying_party' } } server = FederationServer(conf=op_conf) endpoint_context = server.get_endpoint_context() # _clients = yaml.safe_load(io.StringIO(client_yaml)) # endpoint_context.cdb = _clients["oidc_clients"] # store keys under my own ID endpoint_context.keyjar.import_jwks( endpoint_context.keyjar.export_jwks(True, ""), op_conf["issuer"] ) self.pushed_authorization_endpoint = server.server_get("endpoint", "pushed_authorization") self.authorization_endpoint = server.server_get("endpoint", "authorization") self.registration_endpoint = server.server_get("endpoint", "registration") endpoint_context.federation_entity.collector = DummyCollector( httpd=Publisher(ROOT_DIR), trusted_roots=ANCHOR, root_dir=ROOT_DIR)
class TestEndpoint(object): @pytest.fixture(autouse=True) def create_setup(self): # First the RP config = { 'behaviour': { 'federation_types_supported': ['automatic'] }, 'issuer': "https://op.ntnu.no", 'keys': {'key_defs': KEYSPEC}, "federation": { "endpoint": { "fetch": { "path": "fetch", "class": Fetch, "kwargs": {"client_authn_method": None}, } }, 'entity_id': RP_ENTITY_ID, "trusted_roots": ANCHOR, "authority_hints": ['https://ntnu.no'], "entity_type": 'openid_relying_party', "opponent_entity_type": 'openid_provider' } } self.entity = FederationRP(config=config) service_context = self.entity.get_service_context() service_context.federation_entity.collector = DummyCollector( trusted_roots=ANCHOR, root_dir=ROOT_DIR) # The RP has/supports 2 services self.discovery_service = FedProviderInfoDiscovery(self.entity.client_get) self.registration_service = RPRegistration(self.entity.client_get) # self.authorization_service = FedAuthorization(entity.client_get) # and now for the OP op_entity_id = "https://op.ntnu.no" op_conf = { "issuer": op_entity_id, "password": "******", "token_handler_args": { "jwks_def": { "private_path": "private/token_jwks.json", "read_only": False, "key_defs": [ {"type": "oct", "bytes": 24, "use": ["enc"], "kid": "code"}, {"type": "oct", "bytes": 24, "use": ["enc"], "kid": "refresh"}, ], }, "code": {"lifetime": 600}, "token": { "class": "oidcop.token.jwt_token.JWTToken", "kwargs": { "lifetime": 3600, "add_claims": [ "email", "email_verified", "phone_number", "phone_number_verified", ], "add_claim_by_scope": True, "aud": ["https://example.org/appl"] }, }, "refresh": {"lifetime": 86400}, }, "claims_interface": {"class": "oidcop.session.claims.ClaimsInterface", "kwargs": {}}, "verify_ssl": False, "capabilities": CAPABILITIES, "keys": {"uri_path": "static/jwks.json", "key_defs": KEYSPEC}, "id_token": { "class": IDToken, "kwargs": { "default_claims": { "email": {"essential": True}, "email_verified": {"essential": True}, } }, }, "endpoint": { "provider_config": { "path": ".well-known/openid-configuration", "class": ProviderConfiguration, "kwargs": {}, }, "registration": { "path": "registration", "class": OPRegistration, "kwargs": {}, }, "authorization": { "path": "authorization", "class": Authorization, "kwargs": { "response_types_supported": [ " ".join(x) for x in RESPONSE_TYPES_SUPPORTED ], "response_modes_supported": ["query", "fragment", "form_post"], "claims_parameter_supported": True, "request_parameter_supported": True, "request_uri_parameter_supported": True, }, }, "pushed_authorization": { "path": "pushed_authorization", "class": PushedAuthorization, "kwargs": { "client_authn_method": [ "client_secret_post", "client_secret_basic", "client_secret_jwt", "private_key_jwt", ] }, }, }, "authentication": { "anon": { "acr": "http://www.swamid.se/policy/assurance/al1", "class": "oidcop.user_authn.user.NoAuthn", "kwargs": {"user": "******"}, } }, "template_dir": "template", "cookie_handler": { "class": CookieHandler, "kwargs": { "keys": {"key_defs": COOKIE_KEYDEFS}, "name": { "session": "oidc_op", "register": "oidc_op_reg", "session_management": "oidc_op_sman" } }, }, 'add_on': { "automatic_registration": { "function": "fedservice.op.add_on.automatic_registration.add_support", "kwargs": { "new_id": False, # default False "where": ["pushed_authorization"] } } }, "federation": { "endpoint": { "fetch": { "path": "fetch", "class": Fetch, "kwargs": {"client_authn_method": None}, } }, "entity_id": op_entity_id, "trusted_roots": ANCHOR, "authority_hints": ['https://ntnu.no'], "entity_type": 'openid_relying_party', "opponent_entity_type": 'openid_relying_party' } } server = FederationServer(conf=op_conf) endpoint_context = server.get_endpoint_context() # _clients = yaml.safe_load(io.StringIO(client_yaml)) # endpoint_context.cdb = _clients["oidc_clients"] # store keys under my own ID endpoint_context.keyjar.import_jwks( endpoint_context.keyjar.export_jwks(True, ""), op_conf["issuer"] ) self.pushed_authorization_endpoint = server.server_get("endpoint", "pushed_authorization") self.authorization_endpoint = server.server_get("endpoint", "authorization") self.registration_endpoint = server.server_get("endpoint", "registration") endpoint_context.federation_entity.collector = DummyCollector( httpd=Publisher(ROOT_DIR), trusted_roots=ANCHOR, root_dir=ROOT_DIR) def test_pushed_auth_urlencoded(self): # since all endpoint used the same endpoint_context I can grab anyone _op_context = self.registration_endpoint.server_get("endpoint_context") # This is cheating. Getting the OP's provider info _fe = self.registration_service.client_get("service_context").federation_entity trust_chain = TrustChain() trust_chain.metadata = _op_context.provider_info trust_chain.anchor = "https://feide.no" trust_chain.verified_chain = [{'iss': "https://ntnu.no"}] self.discovery_service.update_service_context([trust_chain]) # and the OP's federation keys _op_context.federation_entity.context.keyjar.import_jwks( read_info(os.path.join(ROOT_DIR, 'op.ntnu.no'), 'op.ntnu.no', 'jwks'), issuer_id=_op_context.provider_info['issuer']) # Add RP's OIDC keys to the OP's keyjar. _op_context.keyjar.import_jwks( self.discovery_service.client_get("service_context").keyjar.export_jwks(issuer_id=""), RP_ENTITY_ID ) authn_request = AuthorizationRequest( response_type="code", state="af0ifjsldkj", client_id=RP_ENTITY_ID, redirect_uri="{}/callback".format(RP_ENTITY_ID), code_challenge="K2-ltc83acc4h0c9w6ESC_rEMTJ3bww-uCHaoeK1t8U", code_challenge_method="S256", scope=["ais", "openid"] ) # Create the private_key_jwt assertion _jwt = JWT(self.registration_service.client_get("service_context").keyjar, iss=RP_ENTITY_ID, sign_alg="RS256") _jwt.with_jti = True _assertion = _jwt.pack( { "aud": [_op_context.provider_info["pushed_authorization_request_endpoint"]] }) authn_request.update({"client_assertion": _assertion, "client_assertion_type": JWT_BEARER}) _req = self.pushed_authorization_endpoint.parse_request(authn_request) assert isinstance(_req, AuthorizationRequest) assert set(_req.keys()) == { "state", "redirect_uri", "response_type", "scope", "code_challenge_method", "client_id", "code_challenge", "client_assertion", "client_assertion_type", '__verified_client_assertion' } # Should have a registered client now assert set(_op_context.cdb.keys()) == {RP_ENTITY_ID} def test_pushed_auth_urlencoded_process(self): # since all endpoint used the same endpoint_context I can grab anyone _context = self.registration_endpoint.server_get("endpoint_context") # This is cheating. Getting the OP's provider info _fe = self.registration_service.client_get("service_context").federation_entity trust_chain = TrustChain() trust_chain.metadata = _context.provider_info trust_chain.anchor = "https://feide.no" trust_chain.verified_chain = [{'iss': "https://ntnu.no"}] self.discovery_service.update_service_context([trust_chain]) _rp_context = self.discovery_service.client_get("service_context") # add the OP's federation keys to the RP _rp_context.federation_entity.context.keyjar.import_jwks( read_info(os.path.join(ROOT_DIR, 'op.ntnu.no'), 'op.ntnu.no', 'jwks'), issuer_id=_context.provider_info['issuer']) # Add RP's keys to the OP's OIDC keyjar. _context.keyjar.import_jwks( _rp_context.keyjar.export_jwks(issuer_id=""), RP_ENTITY_ID ) authn_request = AuthorizationRequest( response_type="code", state="af0ifjsldkj", client_id=RP_ENTITY_ID, redirect_uri="{}/callback".format(RP_ENTITY_ID), code_challenge="K2-ltc83acc4h0c9w6ESC_rEMTJ3bww-uCHaoeK1t8U", code_challenge_method="S256", scope=["ais", "openid"] ) # Create the private_key_jwt assertion _jwt = JWT(self.registration_service.client_get("service_context").keyjar, iss=RP_ENTITY_ID, sign_alg="RS256") _jwt.with_jti = True _assertion = _jwt.pack( { "aud": [_context.provider_info[ "pushed_authorization_request_endpoint"]] }) authn_request.update({"client_assertion": _assertion, "client_assertion_type": JWT_BEARER}) _req = self.pushed_authorization_endpoint.parse_request(authn_request) assert isinstance(_req, AuthorizationRequest) assert set(_req.keys()) == { "state", "redirect_uri", "response_type", "scope", "code_challenge_method", "client_id", "code_challenge", "client_assertion", "client_assertion_type", "__verified_client_assertion" } _resp = self.pushed_authorization_endpoint.process_request(_req) assert _resp["return_uri"] == authn_request["redirect_uri"] # And now for the authorization request with the OP provided request_uri authn_request["request_uri"] = _resp["http_response"]["request_uri"] for parameter in ["code_challenge", "code_challenge_method", "client_assertion", "client_assertion_type"]: del authn_request[parameter] _req = self.authorization_endpoint.parse_request(authn_request) assert "code_challenge" in _req
class TestRpService(object): @pytest.fixture(autouse=True) def rp_service_setup(self): entity_id = 'https://foodle.uninett.no' config = { 'client_id': entity_id, 'client_secret': 'a longesh password', 'redirect_uris': ['https://example.com/cli/authz_cb'], "keys": { "uri_path": "static/jwks.json", "key_defs": KEY_DEFS }, "client_preferences": { "grant_types": ['authorization_code', 'implicit', 'refresh_token'], "id_token_signed_response_alg": "ES256", "token_endpoint_auth_method": "client_secret_basic", "federation_type": ['automatic'] }, "federation": { "entity_id": entity_id, "keys": { "uri_path": "static/fed_jwks.json", "key_defs": KEY_DEFS }, "endpoint": { "fetch": { "path": "fetch", "class": Fetch, "kwargs": { "client_authn_method": None }, } }, "trusted_roots": ANCHOR, "authority_hints": ['https://ntnu.no'], "entity_type": 'openid_relying_party', "opponent_entity_type": 'openid_provider', } } oidc_service = DEFAULT_OIDC_SERVICES.copy() oidc_service.update(DEFAULT_OIDC_FED_SERVICES) self.entity = FederationRP(services=oidc_service, config=config) httpc = Publisher(os.path.join(BASE_PATH, 'base_data')) _context = self.entity.client_get("service_context") # The test data collector _context.federation_entity.collector = DummyCollector( trusted_roots=ANCHOR, httpd=httpc, root_dir=os.path.join(BASE_PATH, 'base_data')) self.disco_service = self.entity.client_get("service", 'provider_info') self.registration_service = self.entity.client_get( "service", 'registration') def test_1(self): _info = self.disco_service.get_request_parameters( iss='https://ntnu.no/op') assert set(_info.keys()) == {'url', 'iss'} p = urlparse(_info['url']) assert p.scheme == 'https' assert p.netloc == 'ntnu.no' assert p.path == "/.well-known/openid-federation" _q = parse_qs(p.query) assert list(_q.keys()) == ['iss'] def test_parse_discovery_response(self): _context = self.entity.client_get("service_context") _info = self.disco_service.get_request_parameters( iss='https://op.ntnu.no') http_response = _context.federation_entity.collector.http_cli( 'GET', _info['url']) statements = self.disco_service.parse_response(http_response.text) assert len(statements) == 1 statement = statements[0] assert statement.anchor == 'https://feide.no' self.disco_service.update_service_context(statements) assert set( self.disco_service.client_get("service_context").get( 'behaviour').keys()) == { 'grant_types', 'id_token_signed_response_alg', 'token_endpoint_auth_method', 'federation_type' } def test_create_reqistration_request(self): # get the entity statement from the OP _info = self.disco_service.get_request_parameters( iss='https://op.ntnu.no') _context = self.entity.client_get("service_context") http_response = _context.federation_entity.collector.http_cli( 'GET', _info['url']) # parse the response and collect the trust chains res = self.disco_service.parse_response(http_response.text) self.disco_service.update_service_context(res) # construct the client registration request req_args = {'entity_id': _context.federation_entity.context.entity_id} jws = self.registration_service.construct(request_args=req_args) assert jws _sc = self.registration_service.client_get("service_context") self.registration_service.endpoint = _sc.get( 'provider_info')['federation_registration_endpoint'] # construct the information needed to send the request _info = self.registration_service.get_request_parameters( request_body_type="jose", method="POST") assert set( _info.keys()) == {'method', 'url', 'body', 'headers', 'request'} assert _info['method'] == 'POST' assert _info['url'] == 'https://op.ntnu.no/fedreg' assert _info['headers'] == {'Content-Type': 'application/jose'} _jws = _info['body'] _jwt = factory(_jws) payload = _jwt.jwt.payload() assert set(payload.keys()) == { 'iss', 'jwks', 'exp', 'metadata', 'iat', 'sub', 'authority_hints' } assert set(payload['metadata']['openid_relying_party'].keys()) == { 'application_type', "id_token_signed_response_alg", 'grant_types', 'response_types', "token_endpoint_auth_method", 'federation_type', 'redirect_uris' } def test_parse_registration_response(self): # construct the entity statement the OP should return es_api = FSFetchEntityStatement(os.path.join(BASE_PATH, 'base_data'), iss="op.ntnu.no") jws = es_api.create_entity_statement("op.ntnu.no") # parse the response and collect the trust chains res = self.disco_service.parse_response(jws) _context = self.registration_service.client_get("service_context") _fe = _context.federation_entity _context.issuer = "https://op.ntnu.no" self.disco_service.update_service_context(res) self.registration_service.endpoint = _context.get( 'provider_info')['federation_registration_endpoint'] # construct the client registration request req_args = {'entity_id': _fe.context.entity_id} jws = self.registration_service.construct(request_args=req_args) assert jws # construct the information needed to send the request _info = self.registration_service.get_request_parameters( request_body_type="jose", method="POST") # create the request _req_jwt = factory(_info['body']) payload = _req_jwt.jwt.payload() # The OP as federation entity del _fe.context.keyjar["https://op.ntnu.no"] # make sure I have the private keys _fe.context.keyjar.import_jwks( es_api.keyjar.export_jwks(True, "https://op.ntnu.no"), "https://op.ntnu.no") tree = _fe.collect_statement_chains(payload['iss'], _info['body']) _node = {payload['iss']: (_info['body'], tree)} chains = branch2lists(_node) statements = [ eval_chain(c, _fe.context.keyjar, 'openid_relying_party') for c in chains ] metadata_policy = { "client_id": { "value": "aaaaaaaaa" }, "client_secret": { "value": "bbbbbbbbbb" } } # This is the registration response from the OP _jwt = _fe.context.create_entity_statement( 'https://op.ntnu.no', 'https://foodle.uninett.no', metadata_policy={_fe.context.entity_type: metadata_policy}, trust_anchor_id=statements[0].anchor, authority_hints=['https://feide.no']) claims = self.registration_service.parse_response( _jwt, request=_info['body']) assert set(claims.keys()) == { 'application_type', 'client_secret', 'client_id', "contacts", 'federation_type', 'grant_types', 'id_token_signed_response_alg', 'redirect_uris', 'response_types', 'token_endpoint_auth_method' }
class TestRpServiceAuto(object): @pytest.fixture(autouse=True) def rp_service_setup(self): entity_id = 'https://foodle.uninett.no' config = { 'redirect_uris': ['https://example.com/cli/authz_cb'], "keys": { "uri_path": "static/jwks.json", "key_defs": KEY_DEFS }, "client_preferences": { "grant_types": ['authorization_code', 'implicit', 'refresh_token'], "id_token_signed_response_alg": "ES256", "token_endpoint_auth_method": "client_secret_basic", "federation_type": ['automatic'] }, "services": { 'authorization': { 'class': 'oidcrp.oidc.authorization.Authorization' }, 'access_token': { 'class': 'oidcrp.oidc.access_token.AccessToken' } }, "federation": { "entity_id": entity_id, "keys": { "uri_path": "static/fed_jwks.json", "key_defs": KEY_DEFS }, "endpoint": { "fetch": { "path": "fetch", "class": Fetch, "kwargs": { "client_authn_method": None }, } }, "trusted_roots": ANCHOR, "authority_hints": ['https://ntnu.no'], "entity_type": 'openid_relying_party', "opponent_entity_type": 'openid_provider', } } oidc_service = DEFAULT_OIDC_SERVICES.copy() oidc_service.update(DEFAULT_OIDC_FED_SERVICES) self.entity = FederationRP(services=oidc_service, config=config) _context = self.entity.client_get("service_context") _context.provider_info = {'token_endpoint': "https://op.example.org"} # httpc = Publisher(os.path.join(BASE_PATH, 'base_data')) # # The test data collector # _context.federation_entity.collector = DummyCollector( # trusted_roots=ANCHOR, httpd=httpc, root_dir=os.path.join(BASE_PATH, 'base_data')) def test_construct_client_assertion(self): token_service = self.entity.client_get("service", 'accesstoken') request = AccessTokenRequest() pkj = PrivateKeyJWT() http_args = pkj.construct(request, service=token_service, authn_endpoint='token_endpoint') assert http_args == {} _jws = factory(request["client_assertion"]) _payload = _jws.jwt.payload() assert "iss" in _payload assert _payload["iss"] == 'https://foodle.uninett.no' assert _payload["sub"] == 'https://foodle.uninett.no' assert request['client_assertion_type'] == JWT_BEARER