Esempio n. 1
0
    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 == ''
Esempio n. 2
0
    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
Esempio n. 3
0
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()
Esempio n. 4
0
    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')
Esempio n. 5
0
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)
Esempio n. 6
0
    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
Esempio n. 7
0
    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"]