def test_no_federation_response(self): pc_resp = ProviderConfigurationResponse( issuer=SUNET_OP.iss, response_types_supported=['code'], grant_types_supported=['Bearer'], subject_types_supported=['pairwise'], authorization_endpoint='https://example.com/op/authz', jwks_uri='https://example.com/op/jwks.json', token_endpoint='https://example.com/op/token', id_token_signing_alg_values_supported=['RS256', 'RS384', 'RS512'], userinfo_signing_alg_values_supported=['RS256', 'RS384', 'RS512']) _srv = self.service['provider_info'] _srv.service_context.federation_entity.fo_priority = [ 'https://fo.surfnet.nl' ] resp = _srv.parse_response(pc_resp.to_json(), body_type='json') assert isinstance(resp, ProviderConfigurationResponse) _srv.update_service_context(resp) assert set(_srv.service_context.provider_info.keys()) == { 'issuer', 'response_types_supported', 'version', 'grant_types_supported', 'subject_types_supported', 'authorization_endpoint', 'jwks_uri', 'id_token_signing_alg_values_supported', 'request_uri_parameter_supported', 'request_parameter_supported', 'claims_parameter_supported', 'token_endpoint', 'token_endpoint_auth_methods_supported', 'require_request_uri_registration', 'userinfo_signing_alg_values_supported' } assert _srv.service_context.federation_entity.federation == ''
def test_dynamic_setup(self): user_id = 'acct:[email protected]' _link = Link(rel="http://openid.net/specs/connect/1.0/issuer", href="https://server.example.com") webfinger_response = JRD(subject=user_id, links=[_link]) self.mock_op.register_get_response( '/.well-known/webfinger', webfinger_response.to_json(), 200, {'content-type': "application/json"}) resp = { "authorization_endpoint": "https://server.example.com/connect/authorize", "issuer": "https://server.example.com", "subject_types_supported": ['public'], "token_endpoint": "https://server.example.com/connect/token", "token_endpoint_auth_methods_supported": ["client_secret_basic", "private_key_jwt"], "userinfo_endpoint": "https://server.example.com/connect/user", "check_id_endpoint": "https://server.example.com/connect/check_id", "refresh_session_endpoint": "https://server.example.com/connect/refresh_session", "end_session_endpoint": "https://server.example.com/connect/end_session", "jwks_uri": "https://server.example.com/jwk.json", "registration_endpoint": "https://server.example.com/connect/register", "scopes_supported": ["openid", "profile", "email", "address", "phone"], "response_types_supported": ["code", "code id_token", "token id_token"], "acrs_supported": ["1", "2", "http://id.incommon.org/assurance/bronze"], "user_id_types_supported": ["public", "pairwise"], "userinfo_algs_supported": ["HS256", "RS256", "A128CBC", "A128KW", "RSA1_5"], "id_token_signing_alg_values_supported": ["HS256", "RS256", "A128CBC", "A128KW", "RSA1_5"], "request_object_algs_supported": ["HS256", "RS256", "A128CBC", "A128KW", "RSA1_5"] } pcr = ProviderConfigurationResponse(**resp) self.mock_op.register_get_response( '/.well-known/openid-configuration', pcr.to_json(), 200, {'content-type': "application/json"}) self.mock_op.register_post_response( '/connect/register', registration_callback, 200, {'content-type': "application/json"}) auth_query = self.rph.begin(user_id=user_id) assert auth_query
def create_provider_info_response(fo): sunet_metadata = MetadataStatement() pi_response = ProviderConfigurationResponse( issuer=SUNET_OP.iss, response_types_supported=['code'], grant_types_supported=['Bearer'], subject_types_supported=['pairwise'], authorization_endpoint='https://example.com/op/authz', jwks_uri='https://example.com/op/jwks.json', token_endpoint='https://example.com/op/token', id_token_signing_alg_values_supported=['RS256', 'RS384', 'RS512'], userinfo_signing_alg_values_supported=['RS256', 'RS384', 'RS512']) clear_metadata_statements(FEDENT.values()) _ = create_compounded_metadata_statement( [SUNET_OP.iss, ORG_SUNET.iss, fo.iss], FEDENT, { ORG_SUNET.iss: sunet_metadata, SUNET_OP.iss: pi_response }) # clean copy pi_response = ProviderConfigurationResponse( issuer=SUNET_OP.iss, response_types_supported=['code'], grant_types_supported=['Bearer'], subject_types_supported=['pairwise'], authorization_endpoint='https://example.com/op/authz', jwks_uri='https://example.com/op/jwks.json', token_endpoint='https://example.com/op/token', id_token_signing_alg_values_supported=['RS256', 'RS384', 'RS512'], userinfo_signing_alg_values_supported=['RS256', 'RS384', 'RS512']) SUNET_OP.add_sms_spec_to_request(pi_response) resp = SUNET_OP.self_sign(pi_response) return resp.to_json()
def test_begin_2(self): ISS_ID = "https://op.example.org" OP_KEYS = build_keyjar(DEFAULT_KEY_DEFS) # The 4 steps of client_setup client = self.rph.init_client(ISS_ID) with responses.RequestsMock() as rsps: request_uri = '{}/.well-known/openid-configuration'.format(ISS_ID) _jws = ProviderConfigurationResponse( issuer=ISS_ID, authorization_endpoint='{}/authorization'.format(ISS_ID), jwks_uri='{}/jwks.json'.format(ISS_ID), response_types_supported=[ 'code', 'id_token', 'id_token token' ], subject_types_supported=['public'], id_token_signing_alg_values_supported=["RS256", "ES256"], token_endpoint='{}/token'.format(ISS_ID), registration_endpoint='{}/register'.format(ISS_ID)).to_json() rsps.add("GET", request_uri, body=_jws, status=200) rsps.add("GET", '{}/jwks.json'.format(ISS_ID), body=OP_KEYS.export_jwks_as_json(), status=200) issuer = self.rph.do_provider_info(client) # Calculating request so I can build a reasonable response self.rph.add_callbacks(client.service_context) # Publishing a JWKS instead of a JWKS_URI client.service_context.jwks_uri = '' client.service_context.jwks = client.service_context.keyjar.export_jwks( ) _req = client.service['registration'].construct_request() with responses.RequestsMock() as rsps: request_uri = client.service_context.get( 'provider_info')["registration_endpoint"] _jws = RegistrationResponse( client_id="client uno", client_secret="VerySecretAndLongEnough", **_req.to_dict()).to_json() rsps.add("POST", request_uri, body=_jws, status=200) self.rph.do_client_registration(client, ISS_ID) assert 'jwks' in client.service_context.get('registration_response')
es = EntityStatement().from_json(txt) now = utc_time_sans_frac() es['iat'] = now es['exp'] = now + 3600 print("6.1.2", es.verify()) # ============== 6.2.2 ================== sec = "6.2.2" print("-" * 20, sec, "-" * 20) txt = open("{}.json".format(sec)).read() ps = ProviderConfigurationResponse().from_json(txt) if 'iat' in ps or 'exp' in ps: now = utc_time_sans_frac() es['iat'] = now es['exp'] = now + 3600 print(sec, es.verify()) # ============== A.1.* ================== for sec in ['A.1.1', 'A.1.2', 'A.1.3', 'A.1.4', 'A.1.5', 'A.1.6', 'A.1.7']: print("-" * 20, sec, "-" * 20) txt = open("{}.json".format(sec)).read() es = EntityStatement().from_json(txt)
def parse_federation_registration_response(self, resp, **kwargs): """ Receives a dynamic client registration response, :param resp: An entity statement instance :return: A set of metadata claims """ _context = self.client_get("service_context") _fe = _context.federation_entity _fe_ctx = _fe.context # Can not collect trust chain. Have to verify the signed JWT with keys I have kj = _fe_ctx.keyjar _jwt = factory(resp) entity_statement = _jwt.verify_compact(resp, keys=kj.get_jwt_verify_keys(_jwt.jwt)) _trust_anchor_id = self.get_trust_anchor_id(entity_statement) logger.debug("trust_anchor_id: {}".format(_trust_anchor_id)) chosen = None for op_statement in _fe_ctx.op_statements: if op_statement.anchor == _trust_anchor_id: chosen = op_statement break if not chosen: raise ValueError('No matching federation operator') # based on the Federation ID, conclude which OP config to use op_claims = chosen.metadata logger.debug("OP claims: {}".format(op_claims)) # _sc.trust_path = (chosen.anchor, _fe.op_paths[statement.anchor][0]) _context.provider_info = ProviderConfigurationResponse(**op_claims) # To create RPs metadata collect the trust chains tree = {} for ah in _fe_ctx.authority_hints: tree[ah] = _fe.collector.collect_intermediate(_fe_ctx.entity_id, ah) _node = {_fe_ctx.entity_id: (resp, tree)} chains = branch2lists(_node) logger.debug("%d chains", len(chains)) logger.debug("Evaluate policy chains") # Get the policies policy_chains_tup = [eval_policy_chain(c, _fe_ctx.keyjar, _fe_ctx.entity_type) for c in chains] # Weed out unusable chains policy_chains_tup = [pct for pct in policy_chains_tup if pct is not None] # Should leave me with one. The one ending in the chosen trust anchor. policy_chains_tup = [pct for pct in policy_chains_tup if pct[0] == _trust_anchor_id] if policy_chains_tup == []: logger.warning("No chain that ends in chosen trust anchor (%s)", _trust_anchor_id) raise ValueError("No trust chain that ends in chosen trust anchor (%s)", _trust_anchor_id) _policy = combine_policy(policy_chains_tup[0][1], entity_statement['metadata_policy'][_fe_ctx.entity_type]) logger.debug("Effective policy: {}".format(_policy)) _req = kwargs.get("request") if _req is None: _req = kwargs.get("request_body") _uev = unverified_entity_statement(_req) logger.debug("Registration request: {}".format(_uev)) _query = _uev["metadata"][_fe_ctx.entity_type] _resp = apply_policy(_query, _policy) _context.set("registration_response", _resp) return _resp
def test_begin(self): ISS_ID = "https://op.example.org" OP_KEYS = build_keyjar(DEFAULT_KEY_DEFS) # The 4 steps of client_setup client = self.rph.init_client(ISS_ID) with responses.RequestsMock() as rsps: request_uri = '{}/.well-known/openid-configuration'.format(ISS_ID) _jws = ProviderConfigurationResponse( issuer=ISS_ID, authorization_endpoint='{}/authorization'.format(ISS_ID), jwks_uri='{}/jwks.json'.format(ISS_ID), response_types_supported=[ 'code', 'id_token', 'id_token token' ], subject_types_supported=['public'], id_token_signing_alg_values_supported=["RS256", "ES256"], token_endpoint='{}/token'.format(ISS_ID), registration_endpoint='{}/register'.format(ISS_ID)).to_json() rsps.add("GET", request_uri, body=_jws, status=200) rsps.add("GET", '{}/jwks.json'.format(ISS_ID), body=OP_KEYS.export_jwks_as_json(), status=200) issuer = self.rph.do_provider_info(client) # Calculating request so I can build a reasonable response self.rph.add_callbacks(client.service_context) _req = client.service['registration'].construct_request() with responses.RequestsMock() as rsps: request_uri = client.service_context.get( 'provider_info')["registration_endpoint"] _jws = RegistrationResponse( client_id="client uno", client_secret="VerySecretAndLongEnough", **_req.to_dict()).to_json() rsps.add("POST", request_uri, body=_jws, status=200) self.rph.do_client_registration(client, ISS_ID) self.rph.issuer2rp[issuer] = client assert set(client.service_context.get('behaviour').keys()) == { 'token_endpoint_auth_method', 'response_types', 'scope', 'application_type', 'application_name' } assert client.service_context.get('client_id') == "client uno" assert client.service_context.get( 'client_secret') == "VerySecretAndLongEnough" assert client.service_context.get('issuer') == ISS_ID res = self.rph.init_authorization(client) assert set(res.keys()) == {'url', 'state'} p = urlparse(res["url"]) assert p.hostname == 'op.example.org' assert p.path == "/authorization" qs = parse_qs(p.query) assert qs['state'] == [res['state']] # PKCE stuff assert 'code_challenge' in qs assert qs["code_challenge_method"] == ["S256"]