Пример #1
0
    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')
Пример #2
0
    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)
Пример #3
0
    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"}
Пример #4
0
    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)
Пример #5
0
    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
Пример #8
0
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'
        }
Пример #9
0
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