From da3f4e7529af63734a34df55d4da0e03532c2b72 Mon Sep 17 00:00:00 2001 From: rhoerbe Date: Thu, 17 Oct 2019 21:06:39 +0300 Subject: [PATCH] enable microservice-based flow to replay AuthnRequest (requires wsgi_app in registered callback) --- src/satosa/backends/base.py | 2 +- src/satosa/backends/github.py | 4 +- src/satosa/backends/linkedin.py | 4 +- src/satosa/backends/oauth.py | 4 +- src/satosa/backends/openid_connect.py | 4 +- src/satosa/backends/orcid.py | 2 +- src/satosa/backends/saml2.py | 25 +++++++------ src/satosa/base.py | 2 +- src/satosa/frontends/base.py | 2 +- src/satosa/frontends/openid_connect.py | 16 ++++---- src/satosa/frontends/ping.py | 4 +- src/satosa/frontends/saml2.py | 24 ++++++------ src/satosa/micro_services/account_linking.py | 4 +- .../micro_services/attribute_authorization.py | 2 +- src/satosa/micro_services/consent.py | 4 +- src/satosa/micro_services/redirect_url.py | 3 +- tests/satosa/backends/test_bitbucket.py | 9 +++-- tests/satosa/backends/test_oauth.py | 6 +-- tests/satosa/backends/test_openid_connect.py | 6 +-- tests/satosa/backends/test_orcid.py | 8 ++-- tests/satosa/backends/test_saml2.py | 26 ++++++------- tests/satosa/frontends/test_saml2.py | 37 +++++++++++-------- tests/satosa/micro_services/test_consent.py | 21 ++++++----- .../micro_services/test_custom_routing.py | 2 +- tests/satosa/test_base.py | 8 ++-- tests/satosa/test_routing.py | 2 +- tests/util.py | 14 +++---- 27 files changed, 129 insertions(+), 116 deletions(-) diff --git a/src/satosa/backends/base.py b/src/satosa/backends/base.py index 8d0432da8..cdb4bf8c7 100644 --- a/src/satosa/backends/base.py +++ b/src/satosa/backends/base.py @@ -32,7 +32,7 @@ def __init__(self, auth_callback_func, internal_attributes, base_url, name): self.base_url = base_url self.name = name - def start_auth(self, context, internal_request): + def start_auth(self, context, internal_request, **kwargs): """ This is the start up function of the backend authorization. diff --git a/src/satosa/backends/github.py b/src/satosa/backends/github.py index 1da9dadbe..48b0a1dc0 100644 --- a/src/satosa/backends/github.py +++ b/src/satosa/backends/github.py @@ -45,7 +45,7 @@ def __init__(self, outgoing, internal_attributes, config, base_url, name): outgoing, internal_attributes, config, base_url, name, 'github', 'id') - def start_auth(self, context, internal_request, get_state=stateID): + def start_auth(self, context, internal_request, get_state=stateID, **kwargs): """ :param get_state: Generates a state to be used in authentication call @@ -75,7 +75,7 @@ def auth_info(self, requrest): UNSPECIFIED, None, self.config['server_info']['authorization_endpoint']) - def _authn_response(self, context): + def _authn_response(self, context, **kwargs): state_data = context.state[self.name] aresp = self.consumer.parse_response( AuthorizationResponse, info=json.dumps(context.request)) diff --git a/src/satosa/backends/linkedin.py b/src/satosa/backends/linkedin.py index cbaa2ea39..ea8709205 100644 --- a/src/satosa/backends/linkedin.py +++ b/src/satosa/backends/linkedin.py @@ -46,7 +46,7 @@ def __init__(self, outgoing, internal_attributes, config, base_url, name): outgoing, internal_attributes, config, base_url, name, 'linkedin', 'id') - def start_auth(self, context, internal_request, get_state=stateID): + def start_auth(self, context, internal_request, get_state=stateID, **kwargs): """ :param get_state: Generates a state to be used in authentication call @@ -76,7 +76,7 @@ def auth_info(self, requrest): UNSPECIFIED, None, self.config['server_info']['authorization_endpoint']) - def _authn_response(self, context): + def _authn_response(self, context, **kwargs): state_data = context.state[self.name] aresp = self.consumer.parse_response( AuthorizationResponse, info=json.dumps(context.request)) diff --git a/src/satosa/backends/oauth.py b/src/satosa/backends/oauth.py index 9136ce6d4..f641ab4a8 100644 --- a/src/satosa/backends/oauth.py +++ b/src/satosa/backends/oauth.py @@ -64,7 +64,7 @@ def __init__(self, outgoing, internal_attributes, config, base_url, name, extern response_type=self.config["response_type"]) self.consumer.client_secret = self.config["client_secret"] - def start_auth(self, context, internal_request, get_state=stateID): + def start_auth(self, context, internal_request, get_state=stateID, **kwargs): """ See super class method satosa.backends.base#start_auth :param get_state: Generates a state to be used in the authentication call. @@ -118,7 +118,7 @@ def _verify_state(self, resp, state_data, state): "Missing or invalid state [%s] in response!" % received_state) - def _authn_response(self, context): + def _authn_response(self, context, **kwargs): """ Handles the authentication response from the AS. diff --git a/src/satosa/backends/openid_connect.py b/src/satosa/backends/openid_connect.py index 60a17d7a3..b36a29420 100644 --- a/src/satosa/backends/openid_connect.py +++ b/src/satosa/backends/openid_connect.py @@ -64,7 +64,7 @@ def __init__(self, auth_callback_func, internal_attributes, config, base_url, na if "response_type" not in config["client"]["auth_req_params"]: config["auth_req_params"]["response_type"] = "code" - def start_auth(self, context, request_info): + def start_auth(self, context, request_info, **kwargs): """ See super class method satosa.backends.base#start_auth :type context: satosa.context.Context @@ -167,7 +167,7 @@ def _get_userinfo(self, state, context): self._check_error_response(userinfo_resp, context) return userinfo_resp.to_dict() - def response_endpoint(self, context, *args): + def response_endpoint(self, context, *args, **kwargs): """ Handles the authentication response from the OP. :type context: satosa.context.Context diff --git a/src/satosa/backends/orcid.py b/src/satosa/backends/orcid.py index aaa18b7e5..3582bce5d 100644 --- a/src/satosa/backends/orcid.py +++ b/src/satosa/backends/orcid.py @@ -60,7 +60,7 @@ def auth_info(self, requrest): UNSPECIFIED, None, self.config['server_info']['authorization_endpoint']) - def _authn_response(self, context): + def _authn_response(self, context, **kwargs): state_data = context.state[self.name] aresp = self.consumer.parse_response( AuthorizationResponse, info=json.dumps(context.request)) diff --git a/src/satosa/backends/saml2.py b/src/satosa/backends/saml2.py index d942817ac..63ca53f29 100644 --- a/src/satosa/backends/saml2.py +++ b/src/satosa/backends/saml2.py @@ -129,7 +129,7 @@ def __init__(self, outgoing, internal_attributes, config, base_url, name): with open(p) as key_file: self.encryption_keys.append(key_file.read()) - def get_idp_entity_id(self, context): + def get_idp_entity_id(self, context, **kwargs): """ :type context: satosa.context.Context :rtype: str | None @@ -164,7 +164,7 @@ def get_idp_entity_id(self, context): ) return entity_id - def start_auth(self, context, internal_req): + def start_auth(self, context, internal_req, **kwargs): """ See super class method satosa.backends.base.BackendModule#start_auth @@ -184,7 +184,7 @@ def start_auth(self, context, internal_req): return self.authn_request(context, entity_id) - def disco_query(self, context): + def disco_query(self, context, **kwargs): """ Makes a request to the discovery server @@ -236,7 +236,7 @@ def construct_requested_authn_context(self, entity_id): return authn_context - def authn_request(self, context, entity_id): + def authn_request(self, context, entity_id, **kwargs): """ Do an authorization request on idp with given entity id. This is the start of the authorization. @@ -294,7 +294,7 @@ def authn_request(self, context, entity_id): context.state[self.name] = {"relay_state": relay_state} return make_saml_response(binding, ht_args) - def authn_response(self, context, binding): + def authn_response(self, context, binding, **kwargs): """ Endpoint for the idp response :type context: satosa.context,Context @@ -326,11 +326,12 @@ def authn_response(self, context, binding): raise SATOSAAuthenticationError(context.state, errmsg) del self.outstanding_queries[req_id] - # check if the relay_state matches the cookie state - if context.state[self.name]["relay_state"] != context.request["RelayState"]: - satosa_logging(logger, logging.DEBUG, - "State did not match relay state for state", context.state) - raise SATOSAAuthenticationError(context.state, "State did not match relay state") + # if the response relay_state exists it must match that from the request + if self.name in context.state and "relay_state" in context.state[self.name]: + if context.state[self.name]["relay_state"] != context.request["RelayState"]: + logger.debug("State did not match relay state for state", extra={'state': context.state}) + raise SATOSAAuthenticationError(context.state, "State did not match relay state") + del context.state[self.name] context.decorate(Context.KEY_BACKEND_METADATA_STORE, self.sp.metadata) if self.config.get(SAMLBackend.KEY_MEMORIZE_IDP): @@ -340,7 +341,7 @@ def authn_response(self, context, binding): context.state.pop(Context.KEY_FORCE_AUTHN, None) return self.auth_callback_func(context, self._translate_response(authn_response, context.state)) - def disco_response(self, context): + def disco_response(self, context, **kwargs): """ Endpoint for the discovery server response @@ -406,7 +407,7 @@ def _translate_response(self, response, state): json.dumps(response.ava, indent=4), state) return internal_resp - def _metadata_endpoint(self, context): + def _metadata_endpoint(self, context, **kwargs): """ Endpoint for retrieving the backend metadata :type context: satosa.context.Context diff --git a/src/satosa/base.py b/src/satosa/base.py index ae041ab0e..856d8f17a 100644 --- a/src/satosa/base.py +++ b/src/satosa/base.py @@ -226,7 +226,7 @@ def _run_bound_endpoint(self, context, spec): :return: response """ try: - return spec(context) + return spec(context, wsgi_app=self) except SATOSAAuthenticationError as error: error.error_id = uuid.uuid4().urn state = json.dumps(error.state.state_dict, indent=4) diff --git a/src/satosa/frontends/base.py b/src/satosa/frontends/base.py index 52840a85c..a21ce4274 100644 --- a/src/satosa/frontends/base.py +++ b/src/satosa/frontends/base.py @@ -26,7 +26,7 @@ def __init__(self, auth_req_callback_func, internal_attributes, base_url, name): self.base_url = base_url self.name = name - def handle_authn_response(self, context, internal_resp): + def handle_authn_response(self, context, internal_resp, **kwargs): """ If an authorization has been successful in a backend, this function is called and is supposed to send an authorization response to the client. diff --git a/src/satosa/frontends/openid_connect.py b/src/satosa/frontends/openid_connect.py index bd5972511..0516a09c8 100644 --- a/src/satosa/frontends/openid_connect.py +++ b/src/satosa/frontends/openid_connect.py @@ -117,7 +117,7 @@ def _init_authorization_state(self): return AuthorizationState(HashBasedSubjectIdentifierFactory(sub_hash_salt), authz_code_db, access_token_db, refresh_token_db, sub_db, **token_lifetimes) - def handle_authn_response(self, context, internal_resp, extra_id_token_claims=None): + def handle_authn_response(self, context, internal_resp, extra_id_token_claims=None, **kwargs): """ See super class method satosa.frontends.base.FrontendModule#handle_authn_response :type context: satosa.context.Context @@ -232,7 +232,7 @@ def _get_authn_request_from_state(self, state): """ return AuthorizationRequest().deserialize(state[self.name]["oidc_request"]) - def client_registration(self, context): + def client_registration(self, context, **kwargs): """ Handle the OIDC dynamic client registration. :type context: satosa.context.Context @@ -247,7 +247,7 @@ def client_registration(self, context): except InvalidClientRegistrationRequest as e: return BadRequest(e.to_json(), content="application/json") - def provider_config(self, context): + def provider_config(self, context, **kwargs): """ Construct the provider configuration information (served at /.well-known/openid-configuration). :type context: satosa.context.Context @@ -270,7 +270,7 @@ def _get_approved_attributes(self, provider_supported_claims, authn_req): requested_claims.extend(authn_req["claims"][k].keys()) return set(provider_supported_claims).intersection(set(requested_claims)) - def _handle_authn_request(self, context): + def _handle_authn_request(self, context, **kwargs): """ Parse and verify the authentication request into an internal request. :type context: satosa.context.Context @@ -315,7 +315,7 @@ def _handle_authn_request(self, context): authn_req)) return internal_req - def handle_authn_request(self, context): + def handle_authn_request(self, context, **kwargs): """ Handle an authentication request and pass it on to the backend. :type context: satosa.context.Context @@ -329,7 +329,7 @@ def handle_authn_request(self, context): return internal_req return self.auth_req_callback_func(context, internal_req) - def jwks(self, context): + def jwks(self, context, **kwargs): """ Construct the JWKS document (served at /jwks). :type context: satosa.context.Context @@ -340,7 +340,7 @@ def jwks(self, context): """ return Response(json.dumps(self.provider.jwks), content="application/json") - def token_endpoint(self, context): + def token_endpoint(self, context, **kwargs): """ Handle token requests (served at /token). :type context: satosa.context.Context @@ -364,7 +364,7 @@ def token_endpoint(self, context): error_resp = TokenErrorResponse(error=e.oauth_error, error_description=str(e)) return BadRequest(error_resp.to_json(), content="application/json") - def userinfo_endpoint(self, context): + def userinfo_endpoint(self, context, **kwargs): headers = {"Authorization": context.request_authorization} try: diff --git a/src/satosa/frontends/ping.py b/src/satosa/frontends/ping.py index d0381210a..f9a2ed791 100644 --- a/src/satosa/frontends/ping.py +++ b/src/satosa/frontends/ping.py @@ -19,7 +19,7 @@ def __init__(self, auth_req_callback_func, internal_attributes, config, base_url self.config = config - def handle_authn_response(self, context, internal_resp, extra_id_token_claims=None): + def handle_authn_response(self, context, internal_resp, extra_id_token_claims=None, **kwargs): """ See super class method satosa.frontends.base.FrontendModule#handle_authn_response :type context: satosa.context.Context @@ -47,7 +47,7 @@ def register_endpoints(self, backend_names): return url_map - def ping_endpoint(self, context): + def ping_endpoint(self, context, **kwargs): """ """ logprefix = PingFrontend.logprefix diff --git a/src/satosa/frontends/saml2.py b/src/satosa/frontends/saml2.py index b65003054..3746c75ab 100644 --- a/src/satosa/frontends/saml2.py +++ b/src/satosa/frontends/saml2.py @@ -78,7 +78,7 @@ def __init__(self, auth_req_callback_func, internal_attributes, config, base_url self.KEY_CUSTOM_ATTR_RELEASE) self.idp = None - def handle_authn_response(self, context, internal_response): + def handle_authn_response(self, context, internal_response, **kwargs): """ See super class method satosa.frontends.base.FrontendModule#handle_authn_response :type context: satosa.context.Context @@ -87,7 +87,7 @@ def handle_authn_response(self, context, internal_response): """ return self._handle_authn_response(context, internal_response, self.idp) - def handle_authn_request(self, context, binding_in): + def handle_authn_request(self, context, binding_in, **kwargs): """ This method is bound to the starting endpoint of the authentication. @@ -174,7 +174,7 @@ def _validate_config(self, config): except KeyError as e: raise ValueError("Missing configuration key: %s" % key) from e - def _handle_authn_request(self, context, binding_in, idp): + def _handle_authn_request(self, context, binding_in, idp, **kwargs): """ See doc for handle_authn_request method. @@ -286,7 +286,7 @@ def _filter_attributes(self, idp, internal_response, context,): return attributes - def _handle_authn_response(self, context, internal_response, idp): + def _handle_authn_response(self, context, internal_response, idp, **kwargs): """ See super class satosa.frontends.base.FrontendModule @@ -425,7 +425,7 @@ def _handle_backend_error(self, exception, idp): satosa_logging(logger, logging.DEBUG, "HTTPargs: %s" % http_args, exception.state) return make_saml_response(resp_args["binding"], http_args) - def _metadata_endpoint(self, context): + def _metadata_endpoint(self, context, **kwargs): """ Endpoint for retrieving the backend metadata :type context: satosa.context.Context @@ -589,7 +589,7 @@ def _load_endpoints_to_config(self, provider, target_entity_id, config=None): idp_conf["service"]["idp"]["endpoints"][service] = idp_endpoints return idp_conf - def _load_idp_dynamic_endpoints(self, context): + def _load_idp_dynamic_endpoints(self, context, **kwargs): """ Loads an idp server that accepts the target backend name in the endpoint url ex: //sso/redirect @@ -621,7 +621,7 @@ def _load_idp_dynamic_entity_id(self, state): idp_config = IdPConfig().load(idp_config_file, metadata_construction=False) return Server(config=idp_config) - def handle_authn_request(self, context, binding_in): + def handle_authn_request(self, context, binding_in, **kwargs): """ Loads approved endpoints dynamically See super class satosa.frontends.saml2.SAMLFrontend#handle_authn_request @@ -637,7 +637,7 @@ def handle_authn_request(self, context, binding_in): idp = self._load_idp_dynamic_endpoints(context) return self._handle_authn_request(context, binding_in, idp) - def _create_state_data(self, context, resp_args, relay_state): + def _create_state_data(self, context, resp_args, relay_state, **kwargs): """ Adds the frontend idp entity id to state See super class satosa.frontends.saml2.SAMLFrontend#save_state @@ -661,7 +661,7 @@ def handle_backend_error(self, exception): idp = self._load_idp_dynamic_entity_id(exception.state) return self._handle_backend_error(exception, idp) - def handle_authn_response(self, context, internal_response): + def handle_authn_response(self, context, internal_response, **kwargs): """ See super class satosa.frontends.base.FrontendModule#handle_authn_response :param context: @@ -708,7 +708,7 @@ class SAMLVirtualCoFrontend(SAMLFrontend): KEY_ORGANIZATION = 'organization' KEY_ORGANIZATION_KEYS = ['display_name', 'name', 'url'] - def handle_authn_request(self, context, binding_in): + def handle_authn_request(self, context, binding_in, **kwargs): """ See super class satosa.frontends.saml2.SAMLFrontend#handle_authn_request @@ -723,7 +723,7 @@ def handle_authn_request(self, context, binding_in): idp = self._create_co_virtual_idp(context) return self._handle_authn_request(context, binding_in, idp) - def handle_authn_response(self, context, internal_response): + def handle_authn_response(self, context, internal_response, **kwargs): """ See super class satosa.frontends.base. FrontendModule#handle_authn_response @@ -734,7 +734,7 @@ def handle_authn_response(self, context, internal_response): return self._handle_authn_response(context, internal_response) - def _handle_authn_response(self, context, internal_response): + def _handle_authn_response(self, context, internal_response, **kwargs): """ """ # Using the context of the current request and saved state from the diff --git a/src/satosa/micro_services/account_linking.py b/src/satosa/micro_services/account_linking.py index 0e849f067..3d36a5974 100644 --- a/src/satosa/micro_services/account_linking.py +++ b/src/satosa/micro_services/account_linking.py @@ -35,7 +35,7 @@ def __init__(self, config, *args, **kwargs): self.id_to_attr = config.get("id_to_attr", None) logger.info("Account linking is active") - def _handle_al_response(self, context): + def _handle_al_response(self, context, **kwargs): """ Endpoint for handling account linking service response. When getting here user might have approved or rejected linking their account @@ -108,7 +108,7 @@ def process(self, context, internal_response): context.state[self.name] = internal_response.to_dict() return Redirect("%s/%s" % (self.redirect_url, jws)) - def _get_uuid(self, context, issuer, id): + def _get_uuid(self, context, issuer, id, **kwargs): """ Ask the account linking service for a uuid. If the given issuer/id pair is not linked, then the function will return a ticket. diff --git a/src/satosa/micro_services/attribute_authorization.py b/src/satosa/micro_services/attribute_authorization.py index 1bcaf8cda..3d07ffaa7 100644 --- a/src/satosa/micro_services/attribute_authorization.py +++ b/src/satosa/micro_services/attribute_authorization.py @@ -48,7 +48,7 @@ def __init__(self, config, *args, **kwargs): self.attribute_allow = config.get("attribute_allow", {}) self.attribute_deny = config.get("attribute_deny", {}) - def _check_authz(self, context, attributes, requester, provider): + def _check_authz(self, context, attributes, requester, provider, **kwargs): for attribute_name, attribute_filters in get_dict_defaults(self.attribute_allow, requester, provider).items(): if attribute_name in attributes: if not any([any(filter(re.compile(af).search, attributes[attribute_name])) for af in attribute_filters]): diff --git a/src/satosa/micro_services/consent.py b/src/satosa/micro_services/consent.py index 7841c5993..53e3d3842 100644 --- a/src/satosa/micro_services/consent.py +++ b/src/satosa/micro_services/consent.py @@ -44,7 +44,7 @@ def __init__(self, config, internal_attributes, *args, **kwargs): self.endpoint = "/handle_consent" logger.info("Consent flow is active") - def _handle_consent_response(self, context): + def _handle_consent_response(self, context, **kwargs): """ Endpoint for handling consent service response :type context: satosa.context.Context @@ -78,7 +78,7 @@ def _handle_consent_response(self, context): internal_response.attributes = self._filter_attributes(internal_response.attributes, consent_attributes) return self._end_consent(context, internal_response) - def _approve_new_consent(self, context, internal_response, id_hash): + def _approve_new_consent(self, context, internal_response, id_hash, **kwargs): context.state[STATE_KEY]["internal_resp"] = internal_response.to_dict() consent_args = { diff --git a/src/satosa/micro_services/redirect_url.py b/src/satosa/micro_services/redirect_url.py index d16b7da27..b0d5ec797 100644 --- a/src/satosa/micro_services/redirect_url.py +++ b/src/satosa/micro_services/redirect_url.py @@ -19,7 +19,8 @@ import sys from typing import Tuple import satosa -from .base import RequestMicroService, ResponseMicroService +from satosa.internal import InternalData +from satosa.micro_services.base import RequestMicroService, ResponseMicroService from satosa.micro_services.local_store import LocalStore MIN_PYTHON = (3, 6) diff --git a/tests/satosa/backends/test_bitbucket.py b/tests/satosa/backends/test_bitbucket.py index 192c55a84..6a636f4a0 100644 --- a/tests/satosa/backends/test_bitbucket.py +++ b/tests/satosa/backends/test_bitbucket.py @@ -78,7 +78,7 @@ def create_backend(self): BB_CONFIG, "base_url", "bitbucket") @pytest.fixture - def incoming_authn_response(self, context): + def incoming_authn_response(self, context, **kwargs): context.path = 'bitbucket/sso/redirect' state_data = dict(state=mock_get_state.return_value) context.state[self.bb_backend.name] = state_data @@ -127,7 +127,7 @@ def test_register_endpoints(self): expected_url_map = [('^bitbucket$', self.bb_backend._authn_response)] assert url_map == expected_url_map - def test_start_auth(self, context): + def test_start_auth(self, context, **kwargs): context.path = 'bitbucket/sso/redirect' internal_request = InternalData( subject_type=NAMEID_FORMAT_TRANSIENT, requester='test_requester' @@ -135,7 +135,8 @@ def test_start_auth(self, context): resp = self.bb_backend.start_auth(context, internal_request, - mock_get_state) + mock_get_state, + **kwargs) login_url = resp.message assert login_url.startswith( BB_CONFIG["server_info"]["authorization_endpoint"]) @@ -165,7 +166,7 @@ def test_authn_response(self, incoming_authn_response): self.assert_token_request(**mock_do_access_token_request.call_args[1]) @responses.activate - def test_entire_flow(self, context): + def test_entire_flow(self, context, **kwargs): """ Tests start of authentication (incoming auth req) and receiving auth response. diff --git a/tests/satosa/backends/test_oauth.py b/tests/satosa/backends/test_oauth.py index 0100cfaa9..ea819285b 100644 --- a/tests/satosa/backends/test_oauth.py +++ b/tests/satosa/backends/test_oauth.py @@ -68,7 +68,7 @@ def create_backend(self): self.fb_backend = FacebookBackend(Mock(), INTERNAL_ATTRIBUTES, FB_CONFIG, "base_url", "facebook") @pytest.fixture - def incoming_authn_response(self, context): + def incoming_authn_response(self, context, **kwargs): context.path = 'facebook/sso/redirect' state_data = dict(state=mock_get_state.return_value) context.state[self.fb_backend.name] = state_data @@ -110,7 +110,7 @@ def test_register_endpoints(self): expected_url_map = [('^facebook$', self.fb_backend._authn_response)] assert url_map == expected_url_map - def test_start_auth(self, context): + def test_start_auth(self, context, **kwargs): context.path = 'facebook/sso/redirect' internal_request = InternalData( subject_type=NAMEID_FORMAT_TRANSIENT, requester='test_requester' @@ -142,7 +142,7 @@ def test_authn_response(self, incoming_authn_response): self.assert_token_request(**mock_do_access_token_request.call_args[1]) @responses.activate - def test_entire_flow(self, context): + def test_entire_flow(self, context, **kwargs): """Tests start of authentication (incoming auth req) and receiving auth response.""" responses.add(responses.POST, "https://graph.facebook.com/v2.5/oauth/access_token", diff --git a/tests/satosa/backends/test_openid_connect.py b/tests/satosa/backends/test_openid_connect.py index b282e7725..9c87282d8 100644 --- a/tests/satosa/backends/test_openid_connect.py +++ b/tests/satosa/backends/test_openid_connect.py @@ -129,7 +129,7 @@ def get_redirect_uri_path(self, backend_config): return urlparse(backend_config["client"]["client_metadata"]["redirect_uris"][0]).path.lstrip("/") @pytest.fixture - def incoming_authn_response(self, context, backend_config): + def incoming_authn_response(self, context, backend_config, **kwargs): oidc_state = "my state" context.path = self.get_redirect_uri_path(backend_config) context.request = { @@ -170,7 +170,7 @@ def test_response_endpoint(self, backend_config, internal_attributes, userinfo, assert isinstance(args[1], InternalData) self.assert_expected_attributes(internal_attributes, userinfo, args[1].attributes) - def test_start_auth_redirects_to_provider_authorization_endpoint(self, context, backend_config): + def test_start_auth_redirects_to_provider_authorization_endpoint(self, context, backend_config, **kwargs): auth_response = self.oidc_backend.start_auth(context, None) assert isinstance(auth_response, Response) @@ -186,7 +186,7 @@ def test_start_auth_redirects_to_provider_authorization_endpoint(self, context, assert "nonce" in auth_params @responses.activate - def test_entire_flow(self, context, backend_config, internal_attributes, userinfo): + def test_entire_flow(self, context, backend_config, internal_attributes, userinfo, **kwargs): self.setup_userinfo_endpoint(backend_config["provider_metadata"]["userinfo_endpoint"], userinfo) auth_response = self.oidc_backend.start_auth(context, None) auth_params = dict(parse_qsl(urlparse(auth_response.message).query)) diff --git a/tests/satosa/backends/test_orcid.py b/tests/satosa/backends/test_orcid.py index 5120d4e89..44c326906 100644 --- a/tests/satosa/backends/test_orcid.py +++ b/tests/satosa/backends/test_orcid.py @@ -145,7 +145,7 @@ def setup_userinfo_endpoint(self, userinfo_endpoint_url, userinfo): ) @pytest.fixture - def incoming_authn_response(self, context, backend_config): + def incoming_authn_response(self, context, backend_config, **kwargs): context.path = backend_config["authz_page"] state_data = dict(state=mock_get_state.return_value) context.state[self.orcid_backend.name] = state_data @@ -156,7 +156,7 @@ def incoming_authn_response(self, context, backend_config): return context - def test_start_auth(self, context, backend_config): + def test_start_auth(self, context, backend_config, **kwargs): auth_response = self.orcid_backend.start_auth( context, None, mock_get_state) assert isinstance(auth_response, Response) @@ -191,7 +191,7 @@ def test_authn_response(self, backend_config, userinfo, incoming_authn_response) self.assert_expected_attributes(userinfo, args[1].attributes) @responses.activate - def test_user_information(self, context, backend_config, userinfo): + def test_user_information(self, context, backend_config, userinfo, **kwargs): self.setup_userinfo_endpoint( backend_config["server_info"]["user_info"], userinfo @@ -212,7 +212,7 @@ def test_user_information(self, context, backend_config, userinfo): assert user_attributes["surname"] == ORCID_PERSON_FAMILY_NAME @responses.activate - def test_user_information_private(self, context, backend_config, userinfo_private): + def test_user_information_private(self, context, backend_config, userinfo_private, **kwargs): self.setup_userinfo_endpoint( backend_config["server_info"]["user_info"], userinfo_private diff --git a/tests/satosa/backends/test_saml2.py b/tests/satosa/backends/test_saml2.py index e5e2d905c..544cd4458 100644 --- a/tests/satosa/backends/test_saml2.py +++ b/tests/satosa/backends/test_saml2.py @@ -103,11 +103,11 @@ def get_path_from_url(url): for endp in all_sp_endpoints: assert any(p.match(endp) for p in compiled_regex) - def test_start_auth_defaults_to_redirecting_to_discovery_server(self, context, sp_conf): + def test_start_auth_defaults_to_redirecting_to_discovery_server(self, context, sp_conf, **kwargs): resp = self.samlbackend.start_auth(context, InternalData()) assert_redirect_to_discovery_server(resp, sp_conf, DISCOSRV_URL) - def test_discovery_server_set_in_context(self, context, sp_conf): + def test_discovery_server_set_in_context(self, context, sp_conf, **kwargs): discosrv_url = 'https://my.org/saml_discovery_service' context.decorate( SAMLBackend.KEY_SAML_DISCOVERY_SERVICE_URL, discosrv_url @@ -115,7 +115,7 @@ def test_discovery_server_set_in_context(self, context, sp_conf): resp = self.samlbackend.start_auth(context, InternalData()) assert_redirect_to_discovery_server(resp, sp_conf, discosrv_url) - def test_full_flow(self, context, idp_conf, sp_conf): + def test_full_flow(self, context, idp_conf, sp_conf, **kwargs): test_state_key = "test_state_key_456afgrh" response_binding = BINDING_HTTP_REDIRECT fakeidp = FakeIdP(USERS, config=IdPConfig().load(idp_conf, metadata_construction=False)) @@ -165,7 +165,7 @@ def test_start_auth_redirects_directly_to_mirrored_idp( resp = self.samlbackend.start_auth(context, InternalData()) assert_redirect_to_idp(resp, idp_conf) - def test_redirect_to_idp_if_only_one_idp_in_metadata(self, context, sp_conf, idp_conf): + def test_redirect_to_idp_if_only_one_idp_in_metadata(self, context, sp_conf, idp_conf, **kwargs): sp_conf["metadata"]["inline"] = [create_metadata_from_config_dict(idp_conf)] # instantiate new backend, without any discovery service configured samlbackend = SAMLBackend(None, INTERNAL_ATTRIBUTES, {"sp_config": sp_conf}, "base_url", "saml_backend") @@ -173,13 +173,13 @@ def test_redirect_to_idp_if_only_one_idp_in_metadata(self, context, sp_conf, idp resp = samlbackend.start_auth(context, InternalData()) assert_redirect_to_idp(resp, idp_conf) - def test_authn_request(self, context, idp_conf): + def test_authn_request(self, context, idp_conf, **kwargs): resp = self.samlbackend.authn_request(context, idp_conf["entityid"]) assert_redirect_to_idp(resp, idp_conf) req_params = dict(parse_qsl(urlparse(resp.message).query)) assert context.state[self.samlbackend.name]["relay_state"] == req_params["RelayState"] - def test_authn_response(self, context, idp_conf, sp_conf): + def test_authn_response(self, context, idp_conf, sp_conf, **kwargs): response_binding = BINDING_HTTP_REDIRECT fakesp = FakeSP(SPConfig().load(sp_conf, metadata_construction=False)) fakeidp = FakeIdP(USERS, config=IdPConfig().load(idp_conf, metadata_construction=False)) @@ -199,7 +199,7 @@ def test_authn_response(self, context, idp_conf, sp_conf): @pytest.mark.skipif( saml2.__version__ < '4.6.1', reason="Optional NameID needs pysaml2 v4.6.1 or higher") - def test_authn_response_no_name_id(self, context, idp_conf, sp_conf): + def test_authn_response_no_name_id(self, context, idp_conf, sp_conf, **kwargs): response_binding = BINDING_HTTP_REDIRECT fakesp_conf = SPConfig().load(sp_conf, metadata_construction=False) @@ -232,7 +232,7 @@ def test_authn_response_no_name_id(self, context, idp_conf, sp_conf): assert_authn_response(internal_resp) assert backend.name not in context.state - def test_authn_response_with_encrypted_assertion(self, sp_conf, context): + def test_authn_response_with_encrypted_assertion(self, sp_conf, context, **kwargs): with open(os.path.join( TEST_RESOURCE_BASE_PATH, "idp_metadata_for_encrypted_signed_auth_response.xml" @@ -277,14 +277,14 @@ def test_authn_response_with_encrypted_assertion(self, sp_conf, context): context, internal_resp = samlbackend.auth_callback_func.call_args[0] assert Counter(internal_resp.attributes.keys()) == Counter({"mail", "givenname", "displayname", "surname"}) - def test_backend_reads_encryption_key_from_key_file(self, sp_conf): + def test_backend_reads_encryption_key_from_key_file(self, sp_conf, **kwargs): sp_conf["key_file"] = os.path.join(TEST_RESOURCE_BASE_PATH, "encryption_key.pem") samlbackend = SAMLBackend(Mock(), INTERNAL_ATTRIBUTES, {"sp_config": sp_conf, "disco_srv": DISCOSRV_URL}, "base_url", "samlbackend") assert samlbackend.encryption_keys - def test_backend_reads_encryption_key_from_encryption_keypair(self, sp_conf): + def test_backend_reads_encryption_key_from_encryption_keypair(self, sp_conf, **kwargs): del sp_conf["key_file"] sp_conf["encryption_keypairs"] = [{"key_file": os.path.join(TEST_RESOURCE_BASE_PATH, "encryption_key.pem")}] samlbackend = SAMLBackend(Mock(), INTERNAL_ATTRIBUTES, {"sp_config": sp_conf, @@ -292,13 +292,13 @@ def test_backend_reads_encryption_key_from_encryption_keypair(self, sp_conf): "base_url", "samlbackend") assert samlbackend.encryption_keys - def test_metadata_endpoint(self, context, sp_conf): + def test_metadata_endpoint(self, context, sp_conf, **kwargs): resp = self.samlbackend._metadata_endpoint(context) headers = dict(resp.headers) assert headers["Content-Type"] == "text/xml" assert sp_conf["entityid"] in resp.message - def test_get_metadata_desc(self, sp_conf, idp_conf): + def test_get_metadata_desc(self, sp_conf, idp_conf, **kwargs): sp_conf["metadata"]["inline"] = [create_metadata_from_config_dict(idp_conf)] # instantiate new backend, with a single backing IdP samlbackend = SAMLBackend(None, INTERNAL_ATTRIBUTES, {"sp_config": sp_conf}, "base_url", "saml_backend") @@ -321,7 +321,7 @@ def test_get_metadata_desc(self, sp_conf, idp_conf): assert ui_info["description"] == expected_ui_info["description"] assert ui_info["logo"] == expected_ui_info["logo"] - def test_get_metadata_desc_with_logo_without_lang(self, sp_conf, idp_conf): + def test_get_metadata_desc_with_logo_without_lang(self, sp_conf, idp_conf, **kwargs): # add logo without 'lang' idp_conf["service"]["idp"]["ui_info"]["logo"] = [{"text": "https://idp.example.com/static/logo.png", "width": "120", "height": "60"}] diff --git a/tests/satosa/frontends/test_saml2.py b/tests/satosa/frontends/test_saml2.py index 3e89fd2fa..a1eb006e7 100644 --- a/tests/satosa/frontends/test_saml2.py +++ b/tests/satosa/frontends/test_saml2.py @@ -61,7 +61,7 @@ def construct_base_url_from_entity_id(self, entity_id): def setup_for_authn_req(self, context, idp_conf, sp_conf, nameid_format=None, relay_state="relay_state", internal_attributes=INTERNAL_ATTRIBUTES, extra_config={}, - subject=None): + subject=None, **kwargs): config = {"idp_config": idp_conf, "endpoints": ENDPOINTS} config.update(extra_config) sp_metadata_str = create_metadata_from_config_dict(sp_conf) @@ -142,7 +142,7 @@ def get_path_from_url(url): for endp in all_idp_endpoints: assert any(p.match(endp) for p in compiled_regex) - def test_handle_authn_request(self, context, idp_conf, sp_conf, internal_response): + def test_handle_authn_request(self, context, idp_conf, sp_conf, internal_response, **kwargs): samlfrontend = self.setup_for_authn_req(context, idp_conf, sp_conf) _, internal_req = samlfrontend.handle_authn_request(context, BINDING_HTTP_REDIRECT) assert internal_req.requester == sp_conf["entityid"] @@ -156,7 +156,8 @@ def test_handle_authn_request(self, context, idp_conf, sp_conf, internal_respons for key in resp.ava: assert USERS["testuser1"][key] == resp.ava[key] - def test_create_authn_request_with_subject(self, context, idp_conf, sp_conf, internal_response): + def test_create_authn_request_with_subject(self, context, idp_conf, sp_conf, internal_response, + **kwargs): name_id_value = 'somenameid' name_id = NameID(format=NAMEID_FORMAT_UNSPECIFIED, text=name_id_value) subject = Subject(name_id=name_id) @@ -181,7 +182,8 @@ def test_handle_authn_request_without_name_id_policy_and_metadata_without_name_i _, internal_req = samlfrontend.handle_authn_request(context, BINDING_HTTP_REDIRECT) assert internal_req.subject_type == NAMEID_FORMAT_TRANSIENT - def test_handle_authn_response_without_relay_state(self, context, idp_conf, sp_conf, internal_response): + def test_handle_authn_response_without_relay_state(self, context, idp_conf, sp_conf, + internal_response, **kwargs): samlfrontend = self.setup_for_authn_req(context, idp_conf, sp_conf, relay_state=None) _, internal_req = samlfrontend.handle_authn_request(context, BINDING_HTTP_REDIRECT) assert internal_req.requester == sp_conf["entityid"] @@ -263,7 +265,8 @@ def test_get_filter_attributes_with_sp_requested_attributes_without_friendlyname assert set(filtered_attributes) == set(["edupersontargetedid", "edupersonprincipalname", "edupersonaffiliation", "mail", "displayname", "sn", "givenname"]) - def test_acr_mapping_in_authn_response(self, context, idp_conf, sp_conf, internal_response): + def test_acr_mapping_in_authn_response(self, context, idp_conf, sp_conf, internal_response, + **kwargs): eidas_loa_low = "http://eidas.europa.eu/LoA/low" loa = {"": eidas_loa_low} samlfrontend = self.setup_for_authn_req(context, idp_conf, sp_conf, extra_config={"acr_mapping": loa}) @@ -274,7 +277,8 @@ def test_acr_mapping_in_authn_response(self, context, idp_conf, sp_conf, interna authn_context_class_ref = resp.assertion.authn_statement[0].authn_context.authn_context_class_ref assert authn_context_class_ref.text == eidas_loa_low - def test_acr_mapping_per_idp_in_authn_response(self, context, idp_conf, sp_conf, internal_response): + def test_acr_mapping_per_idp_in_authn_response(self, context, idp_conf, sp_conf, + internal_response, **kwargs): expected_loa = "LoA1" loa = {"": "http://eidas.europa.eu/LoA/low", idp_conf["entityid"]: expected_loa} samlfrontend = self.setup_for_authn_req(context, idp_conf, sp_conf, extra_config={"acr_mapping": loa}) @@ -294,8 +298,9 @@ def test_acr_mapping_per_idp_in_authn_response(self, context, idp_conf, sp_conf, ([RESEARCH_AND_EDUCATION, NREN], "swamid", swamid.RELEASE[""] + swamid.RELEASE[(RESEARCH_AND_EDUCATION, NREN)]), ([SFS_1993_1153], "swamid", swamid.RELEASE[""] + swamid.RELEASE[SFS_1993_1153]), ]) - def test_respect_sp_entity_categories(self, context, entity_category, entity_category_module, expected_attributes, - idp_conf, sp_conf, internal_response): + def test_respect_sp_entity_categories(self, context, entity_category, entity_category_module, + expected_attributes, idp_conf, sp_conf, + internal_response, **kwargs): idp_metadata_str = create_metadata_from_config_dict(idp_conf) idp_conf["service"]["idp"]["policy"]["default"]["entity_categories"] = [entity_category_module] if all(entity_category): # don't insert empty entity category @@ -321,22 +326,23 @@ def test_respect_sp_entity_categories(self, context, entity_category, entity_cat resp = self.get_auth_response(samlfrontend, context, internal_response, sp_conf, idp_metadata_str) assert Counter(resp.ava.keys()) == Counter(expected_attributes) - def test_sp_metadata_including_uiinfo_display_name(self, context, idp_conf, sp_conf): + def test_sp_metadata_including_uiinfo_display_name(self, context, idp_conf, sp_conf, **kwargs): sp_conf["service"]["sp"]["ui_info"] = dict(display_name="Test SP") samlfrontend = self.setup_for_authn_req(context, idp_conf, sp_conf) display_names = samlfrontend._get_sp_display_name(samlfrontend.idp, sp_conf["entityid"]) assert display_names[0]["text"] == "Test SP" - def test_sp_metadata_including_uiinfo_without_display_name(self, context, idp_conf, sp_conf): + def test_sp_metadata_including_uiinfo_without_display_name(self, context, idp_conf, sp_conf, + **kwargs): sp_conf["service"]["sp"]["ui_info"] = dict(information_url="http://info.example.com") samlfrontend = self.setup_for_authn_req(context, idp_conf, sp_conf) assert samlfrontend._get_sp_display_name(samlfrontend.idp, sp_conf["entityid"]) is None - def test_sp_metadata_without_uiinfo(self, context, idp_conf, sp_conf): + def test_sp_metadata_without_uiinfo(self, context, idp_conf, sp_conf, **kwargs): samlfrontend = self.setup_for_authn_req(context, idp_conf, sp_conf) assert samlfrontend._get_sp_display_name(samlfrontend.idp, sp_conf["entityid"]) is None - def test_metadata_endpoint(self, context, idp_conf): + def test_metadata_endpoint(self, context, idp_conf, **kwargs): conf = {"idp_config": idp_conf, "endpoints": ENDPOINTS} samlfrontend = SAMLFrontend(lambda ctx, req: None, INTERNAL_ATTRIBUTES, conf, "base_url", "saml_frontend") samlfrontend.register_endpoints(["todo"]) @@ -345,8 +351,9 @@ def test_metadata_endpoint(self, context, idp_conf): assert headers["Content-Type"] == "text/xml" assert idp_conf["entityid"] in resp.message - def test_custom_attribute_release_with_less_attributes_than_entity_category(self, context, idp_conf, sp_conf, - internal_response): + def test_custom_attribute_release_with_less_attributes_than_entity_category( + self, context, idp_conf, sp_conf, + internal_response, **kwargs): idp_metadata_str = create_metadata_from_config_dict(idp_conf) idp_conf["service"]["idp"]["policy"]["default"]["entity_categories"] = ["swamid"] sp_conf["entity_category"] = [SFS_1993_1153] @@ -392,7 +399,7 @@ def test_load_endpoints_to_config(self): idp_config = self.frontend._load_endpoints_to_config(self.BACKEND, self.TARGET_ENTITY_ID) self.assert_dynamic_endpoints(idp_config["service"]["idp"]["endpoints"]["single_sign_on_service"]) - def test_load_idp_dynamic_endpoints(self, context): + def test_load_idp_dynamic_endpoints(self, context, **kwargs): context.path = "{}/{}/sso/redirect".format(self.BACKEND, self.TARGET_ENTITY_ID) context.target_backend = self.BACKEND idp = self.frontend._load_idp_dynamic_endpoints(context) diff --git a/tests/satosa/micro_services/test_consent.py b/tests/satosa/micro_services/test_consent.py index 247b74868..ebc39b9fc 100644 --- a/tests/satosa/micro_services/test_consent.py +++ b/tests/satosa/micro_services/test_consent.py @@ -123,7 +123,7 @@ def test_consent_registration(self, consent_config): @responses.activate def test_consent_handles_connection_error(self, context, internal_response, internal_request, - consent_verify_endpoint_regex): + consent_verify_endpoint_regex, **kwargs): responses.add(responses.GET, consent_verify_endpoint_regex, body=requests.ConnectionError("No connection")) @@ -139,7 +139,7 @@ def test_consent_handles_connection_error(self, context, internal_response, inte @responses.activate def test_consent_prev_given(self, context, internal_response, internal_request, - consent_verify_endpoint_regex): + consent_verify_endpoint_regex, **kwargs): responses.add(responses.GET, consent_verify_endpoint_regex, status=200, body=json.dumps(FILTER)) @@ -149,7 +149,8 @@ def test_consent_prev_given(self, context, internal_response, internal_request, assert "displayName" in internal_response.attributes def test_consent_full_flow(self, context, consent_config, internal_response, internal_request, - consent_verify_endpoint_regex, consent_registration_endpoint_regex): + consent_verify_endpoint_regex, consent_registration_endpoint_regex, + **kwargs): expected_ticket = "my_ticket" requester_name = [{"lang": "en", "text": "test requester"}] @@ -182,7 +183,8 @@ def test_consent_full_flow(self, context, consent_config, internal_response, int @responses.activate def test_consent_not_given(self, context, consent_config, internal_response, internal_request, - consent_verify_endpoint_regex, consent_registration_endpoint_regex): + consent_verify_endpoint_regex, consent_registration_endpoint_regex, + **kwargs): expected_ticket = "my_ticket" responses.add(responses.GET, consent_verify_endpoint_regex, status=401) @@ -217,9 +219,9 @@ def test_filter_attributes(self): assert Counter(filtered_attributes.keys()) == Counter(FILTER) @responses.activate - def test_manage_consent_filters_attributes_before_send_to_consent_service(self, context, internal_request, - internal_response, - consent_verify_endpoint_regex): + def test_manage_consent_filters_attributes_before_send_to_consent_service( + self, context, internal_request, + internal_response, consent_verify_endpoint_regex, **kwargs): approved_attributes = ["foo", "bar"] # fake previous consent responses.add(responses.GET, consent_verify_endpoint_regex, status=200, @@ -238,8 +240,9 @@ def test_manage_consent_filters_attributes_before_send_to_consent_service(self, assert consent_hash == expected_hash @responses.activate - def test_manage_consent_without_filter_passes_through_all_attributes(self, context, internal_response, - consent_verify_endpoint_regex): + def test_manage_consent_without_filter_passes_through_all_attributes( + self, context, internal_response, + consent_verify_endpoint_regex, **kwargs): # fake previous consent responses.add(responses.GET, consent_verify_endpoint_regex, status=200, body=json.dumps(list(internal_response.attributes.keys()))) diff --git a/tests/satosa/micro_services/test_custom_routing.py b/tests/satosa/micro_services/test_custom_routing.py index 7a5227250..6804957cb 100644 --- a/tests/satosa/micro_services/test_custom_routing.py +++ b/tests/satosa/micro_services/test_custom_routing.py @@ -144,7 +144,7 @@ def test_defaults_to_allow_all_requesters_for_target_entity_without_specific_rul req = InternalData(requester="test_requester") assert decide_service.process(target_context, req) - def test_missing_target_entity_id_from_context(self, context): + def test_missing_target_entity_id_from_context(self, context, **kwargs): target_entity = "entity1" rules = { target_entity: { diff --git a/tests/satosa/test_base.py b/tests/satosa/test_base.py index 0cb365742..32db8a73f 100644 --- a/tests/satosa/test_base.py +++ b/tests/satosa/test_base.py @@ -41,7 +41,7 @@ def test_constuctor_should_raise_exception_if_consent_is_not_last_in_micro_servi with pytest.raises(SATOSAConfigurationError): SATOSABase(satosa_config) - def test_auth_resp_callback_func_user_id_from_attrs_is_used_to_override_user_id(self, context, satosa_config): + def test_auth_resp_callback_func_user_id_from_attrs_is_used_to_override_user_id(self, context, satosa_config, **kwargs): satosa_config["INTERNAL_ATTRIBUTES"]["user_id_from_attrs"] = ["user_id", "domain"] base = SATOSABase(satosa_config) @@ -56,7 +56,7 @@ def test_auth_resp_callback_func_user_id_from_attrs_is_used_to_override_user_id( expected_user_id = "user@example.com" assert internal_resp.subject_id == expected_user_id - def test_auth_req_callback_stores_state_for_consent(self, context, satosa_config): + def test_auth_req_callback_stores_state_for_consent(self, context, satosa_config, **kwargs): base = SATOSABase(satosa_config) context.target_backend = satosa_config["BACKEND_MODULES"][0]["name"] @@ -70,7 +70,7 @@ def test_auth_req_callback_stores_state_for_consent(self, context, satosa_config assert context.state[consent.STATE_KEY]["requester_name"] == internal_req.requester_name assert context.state[consent.STATE_KEY]["filter"] == internal_req.attributes - def test_auth_resp_callback_func_hashes_all_specified_attributes(self, context, satosa_config): + def test_auth_resp_callback_func_hashes_all_specified_attributes(self, context, satosa_config, **kwargs): satosa_config["INTERNAL_ATTRIBUTES"]["hash"] = ["user_id", "mail"] base = SATOSABase(satosa_config) @@ -88,7 +88,7 @@ def test_auth_resp_callback_func_hashes_all_specified_attributes(self, context, for v in attributes[attr] ] - def test_auth_resp_callback_func_respects_user_id_to_attr(self, context, satosa_config): + def test_auth_resp_callback_func_respects_user_id_to_attr(self, context, satosa_config, **kwargs): satosa_config["INTERNAL_ATTRIBUTES"]["user_id_to_attr"] = "user_id" base = SATOSABase(satosa_config) diff --git a/tests/satosa/test_routing.py b/tests/satosa/test_routing.py index be23456ad..82a22fcb6 100644 --- a/tests/satosa/test_routing.py +++ b/tests/satosa/test_routing.py @@ -78,7 +78,7 @@ def test_module_routing(self, url_path, expected_frontend, expected_backend, con frontend = self.router.frontend_routing(context) assert frontend == self.router.frontends[expected_frontend]["instance"] - def test_endpoint_routing_with_unknown_endpoint(self, context): + def test_endpoint_routing_with_unknown_endpoint(self, context, **kwargs): context.path = "unknown" with pytest.raises(SATOSANoBoundEndpointError): self.router.endpoint_routing(context) diff --git a/tests/util.py b/tests/util.py index 12d9ec4ca..13c5402e4 100644 --- a/tests/util.py +++ b/tests/util.py @@ -381,7 +381,7 @@ def __init__(self, start_auth_func=None, internal_attributes=None, self.start_auth_func = start_auth_func self.register_endpoints_func = register_endpoints_func - def start_auth(self, context, request_info, state): + def start_auth(self, context, request_info, state, **kwargs): """ TODO comment :type context: TODO comment @@ -419,7 +419,7 @@ def __init__(self, handle_authn_request_func=None, internal_attributes=None, self.handle_authn_response_func = handle_authn_response_func self.register_endpoints_func = register_endpoints_func - def handle_authn_request(self, context, binding_in): + def handle_authn_request(self, context, binding_in, **kwargs): """ TODO comment @@ -434,7 +434,7 @@ def handle_authn_request(self, context, binding_in): return self.handle_authn_request_func(context, binding_in) return None - def handle_authn_response(self, context, internal_response, state): + def handle_authn_response(self, context, internal_response, state, **kwargs): """ TODO comment :type context: TODO comment @@ -462,10 +462,10 @@ def __init__(self, auth_callback_func, internal_attributes, config, base_url, na def register_endpoints(self): return [("^{}/response$".format(self.name), self.handle_response)] - def start_auth(self, context, internal_request): + def start_auth(self, context, internal_request, **kwargs): return Response("Auth request received, passed to test backend") - def handle_response(self, context): + def handle_response(self, context, **kwargs): auth_info = AuthenticationInformation("test", str(datetime.now()), "test_issuer") internal_resp = InternalData(auth_info=auth_info) internal_resp.attributes = context.request @@ -481,13 +481,13 @@ def register_endpoints(self, backend_names): url_map = [("^{}/{}/request$".format(p, self.name), self.handle_request) for p in backend_names] return url_map - def handle_request(self, context): + def handle_request(self, context, **kwargs): internal_req = InternalData( subject_type=NAMEID_FORMAT_TRANSIENT, requester="test_client" ) return self.auth_req_callback_func(context, internal_req) - def handle_authn_response(self, context, internal_resp): + def handle_authn_response(self, context, internal_resp, **kwargs): return Response("Auth response received, passed to test frontend")