def test_handle_authn_request_without_name_id_policy( self, idp_conf, sp_conf): """ Performs a complete test for the module. The flow should be accepted. """ context, samlfrontend = self.setup_for_authn_req(idp_conf, sp_conf, "") _, internal_req = samlfrontend.handle_authn_request( context, BINDING_HTTP_REDIRECT) assert internal_req.requestor == sp_conf["entityid"] auth_info = AuthenticationInformation(PASSWORD, "2015-09-30T12:21:37Z", "unittest_idp.xml") internal_response = InternalResponse(auth_info=auth_info) internal_response.set_user_id_hash_type(internal_req.user_id_hash_type) internal_response.add_attributes(USERS["testuser1"]) resp = samlfrontend.handle_authn_response(context, internal_response) resp_dict = parse_qs(urlparse(resp.message).query) fakesp = FakeSP(None, config=SPConfig().load(sp_conf, metadata_construction=False)) resp = fakesp.parse_authn_request_response( resp_dict['SAMLResponse'][0], BINDING_HTTP_REDIRECT) for key in resp.ava: assert USERS["testuser1"][key] == resp.ava[key]
def internal_response(self): auth_info = AuthenticationInformation("auth_class_ref", "timestamp", "issuer") internal_response = InternalResponse(auth_info=auth_info) internal_response.requester = "client" internal_response.attributes = ATTRIBUTES return internal_response
def setup(self, signing_key_path): self.account_linking_config = { "enable": True, "rest_uri": "https://localhost:8167", "redirect": "https://localhost:8167/approve", "endpoint": "handle_account_linking", "sign_key": signing_key_path, "verify_ssl": False } self.satosa_config = { "BASE": "https://proxy.example.com", "USER_ID_HASH_SALT": "qwerty", "COOKIE_STATE_NAME": "SATOSA_SATE", "STATE_ENCRYPTION_KEY": "ASDasd123", "PLUGIN_PATH": "", "BACKEND_MODULES": "", "FRONTEND_MODULES": "", "INTERNAL_ATTRIBUTES": {}, "ACCOUNT_LINKING": self.account_linking_config } self.callback_func = MagicMock() self.context = Context() state = State() self.context.state = state auth_info = AuthenticationInformation("auth_class_ref", "timestamp", "issuer") self.internal_response = InternalResponse(auth_info=auth_info)
def internal_response(self, idp_conf): auth_info = AuthenticationInformation(PASSWORD, "2015-09-30T12:21:37Z", idp_conf["entityid"]) internal_response = InternalResponse(auth_info=auth_info) internal_response.attributes = AttributeMapper( INTERNAL_ATTRIBUTES).to_internal("saml", USERS["testuser1"]) return internal_response
def test_auth_resp_callback_func_user_id_from_attrs_is_used_to_override_user_id( self, context, satosa_config): satosa_config["INTERNAL_ATTRIBUTES"]["user_id_from_attrs"] = [ "user_id", "domain" ] base = SATOSABase(satosa_config) internal_resp = InternalResponse(AuthenticationInformation("", "", "")) internal_resp.attributes = { "user_id": ["user"], "domain": ["@example.com"] } internal_resp.requester = "test_requester" context.state[satosa.base.STATE_KEY] = {"requester": "test_requester"} context.state[satosa.routing. STATE_KEY] = satosa_config["FRONTEND_MODULES"][0]["name"] UserIdHasher.save_state(InternalRequest(UserIdHashType.persistent, ""), context.state) base._auth_resp_callback_func(context, internal_resp) expected_user_id = UserIdHasher.hash_data( satosa_config["USER_ID_HASH_SALT"], "*****@*****.**") expected_user_id = UserIdHasher.hash_id( satosa_config["USER_ID_HASH_SALT"], expected_user_id, internal_resp.requester, context.state) assert internal_resp.user_id == expected_user_id
def _translate_response(self, response, issuer, subject_type): """ Translates oidc response to SATOSA internal response. :type response: dict[str, str] :type issuer: str :type subject_type: str :rtype: InternalResponse :param response: Dictioary with attribute name as key. :param issuer: The oidc op that gave the repsonse. :param subject_type: public or pairwise according to oidc standard. :return: A SATOSA internal response. """ oidc_clients = self.get_oidc_clients() subject_type = subject_type auth_info = AuthenticationInformation(UNSPECIFIED, str(datetime.now()), issuer) internal_resp = InternalResponse(auth_info=auth_info) internal_resp.add_attributes( self.converter.to_internal("openid", response)) internal_resp.set_user_id(response["sub"]) if self.config.USER_ID_PARAMAS: user_id = "" for param in self.config.USER_ID_PARAMAS: try: user_id += response[param] except Exception as error: raise SATOSAAuthenticationError from error internal_resp.set_user_id(user_id) return internal_resp
def handle_response(self, context): auth_info = AuthenticationInformation("test", str(datetime.now()), "test_issuer") internal_resp = InternalResponse(auth_info=auth_info) internal_resp.attributes = context.request internal_resp.user_id = "test_user" return self.auth_callback_func(context, internal_resp)
def test_handle_authn_response_returns_id_token_for_verified_affiliation( self, signing_key_path, context, scope_value, affiliation): authn_req = AuthorizationRequest( scope='openid ' + scope_value, client_id='client1', redirect_uri='https://client.example.com', response_type='id_token') context.state[self.frontend.name] = { 'oidc_request': authn_req.to_urlencoded() } internal_response = InternalResponse( AuthenticationInformation(None, str(datetime.now()), 'https://idp.example.com')) internal_response.attributes['affiliation'] = [affiliation] internal_response.user_id = 'user1' resp = self.frontend.handle_authn_response(context, internal_response) auth_resp = AuthorizationResponse().from_urlencoded( urlparse(resp.message).fragment) id_token = IdToken().from_jwt( auth_resp['id_token'], key=[RSAKey(key=rsa_load(signing_key_path))]) assert id_token['iss'] == self.frontend.base_url assert id_token['aud'] == ['client1'] assert id_token['auth_time'] == internal_response.auth_info.timestamp
def test_filter_attribute_not_in_response(self): attribute_filters = {"": {"": {"a0": "foo:bar"}}} filter_service = self.create_filter_service(attribute_filters) resp = InternalResponse(AuthenticationInformation(None, None, None)) resp.attributes = { "a1": ["abc:xyz", "1:foo:bar:2"], } filtered = filter_service.process(None, resp) assert filtered.attributes == {"a1": ["abc:xyz", "1:foo:bar:2"]}
def test_filter_one_attribute_for_one_target_provider(self): target_provider = "test_provider" attribute_filters = {target_provider: {"": {"a1": "foo:bar"}}} filter_service = self.create_filter_service(attribute_filters) resp = InternalResponse( AuthenticationInformation(None, None, target_provider)) resp.attributes = { "a1": ["abc:xyz", "1:foo:bar:2"], } filtered = filter_service.process(None, resp) assert filtered.attributes == {"a1": ["1:foo:bar:2"]}
def test_filter_one_attribute_from_all_target_providers_for_all_requesters( self): attribute_filters = {"": {"": {"a2": "^foo:bar$"}}} filter_service = self.create_filter_service(attribute_filters) resp = InternalResponse(AuthenticationInformation(None, None, None)) resp.attributes = { "a1": ["abc:xyz"], "a2": ["foo:bar", "1:foo:bar:2"], } filtered = filter_service.process(None, resp) assert filtered.attributes == {"a1": ["abc:xyz"], "a2": ["foo:bar"]}
def internal_response(): auth_info = AuthenticationInformation("auth_class_ref", "timestamp", "issuer") internal_response = InternalResponse(auth_info=auth_info) internal_response.set_user_id_hash_type(UserIdHashType.persistent) internal_response.add_attributes({ "displayName": "Test", "co": "example", "sn": "removed_by_filter" }) internal_response.user_id = "usrID" return internal_response
def auth_info(self, request): """ Creates the SATOSA authentication information object. :type request: dict[str, str] :rtype: AuthenticationInformation :param request: The request parameters in the authentication response sent by the OP. :return: How, who and when the autentication took place. """ auth_info = AuthenticationInformation( UNSPECIFIED, None, self.config["server_info"]["authorization_endpoint"]) return auth_info
def test_acr_mapping_per_idp_in_authn_response(self, idp_conf, sp_conf): expected_loa = "LoA1" loa = { "": "http://eidas.europa.eu/LoA/low", idp_conf["entityid"]: expected_loa } base = self.construct_base_url_from_entity_id(idp_conf["entityid"]) conf = { "idp_config": idp_conf, "endpoints": ENDPOINTS, "base": base, "state_id": "state_id", "acr_mapping": loa } samlfrontend = SamlFrontend(None, INTERNAL_ATTRIBUTES, conf) samlfrontend.register_endpoints(["foo"]) idp_metadata_str = create_metadata_from_config_dict( samlfrontend.config) sp_conf["metadata"]["inline"].append(idp_metadata_str) fakesp = FakeSP(None, config=SPConfig().load(sp_conf, metadata_construction=False)) auth_info = AuthenticationInformation(PASSWORD, "2015-09-30T12:21:37Z", idp_conf["entityid"]) internal_response = InternalResponse(auth_info=auth_info) context = Context() context.state = State() resp_args = { "name_id_policy": NameIDPolicy(format=NAMEID_FORMAT_TRANSIENT), "in_response_to": None, "destination": "", "sp_entity_id": None, "binding": BINDING_HTTP_REDIRECT } request_state = samlfrontend.save_state(context, resp_args, "") context.state.add(conf["state_id"], request_state) resp = samlfrontend.handle_authn_response(context, internal_response) resp_dict = parse_qs(urlparse(resp.message).query) resp = fakesp.parse_authn_request_response( resp_dict['SAMLResponse'][0], BINDING_HTTP_REDIRECT) assert len(resp.assertion.authn_statement) == 1 authn_context_class_ref = resp.assertion.authn_statement[ 0].authn_context.authn_context_class_ref assert authn_context_class_ref.text == expected_loa
def setup_for_authn_response(self, context, frontend, auth_req): context.state[frontend.name] = { "oidc_request": auth_req.to_urlencoded() } auth_info = AuthenticationInformation(PASSWORD, "2015-09-30T12:21:37Z", "unittest_idp.xml") internal_response = InternalResponse(auth_info=auth_info) internal_response.attributes = AttributeMapper( INTERNAL_ATTRIBUTES).to_internal("saml", USERS["testuser1"]) internal_response.user_id = USERS["testuser1"]["eduPersonTargetedID"][ 0] return internal_response
def test_authz_deny_fail(self): attribute_deny = {"": {"default": {"a0": ['foo1', 'foo2']}}} attribute_allow = {} authz_service = self.create_authz_service(attribute_allow, attribute_deny) resp = InternalResponse(AuthenticationInformation(None, None, None)) resp.attributes = { "a0": ["foo3"], } try: ctx = Context() ctx.state = dict() authz_service.process(ctx, resp) except SATOSAAuthenticationError as ex: assert False
def test_auth_resp_callback_func_respects_user_id_to_attr( self, context, satosa_config): satosa_config["INTERNAL_ATTRIBUTES"]["user_id_to_attr"] = "user_id" base = SATOSABase(satosa_config) internal_resp = InternalResponse(AuthenticationInformation("", "", "")) internal_resp.user_id = "user1234" context.state[satosa.base.STATE_KEY] = {"requester": "test_requester"} context.state[satosa.routing. STATE_KEY] = satosa_config["FRONTEND_MODULES"][0]["name"] UserIdHasher.save_state(InternalRequest(UserIdHashType.transient, ""), context.state) base._auth_resp_callback_func(context, internal_resp) assert internal_resp.attributes["user_id"] == [internal_resp.user_id]
def _translate_response(self, response, state): """ Translates a saml authorization response to an internal response :type response: saml2.response.AuthnResponse :rtype: satosa.internal_data.InternalResponse :param response: The saml authorization response :return: A translated internal response """ _authn_info = response.authn_info()[0] timestamp = response.assertion.authn_statement[0].authn_instant issuer = response.response.issuer.text auth_class_ref = _authn_info[0] auth_info = AuthenticationInformation(auth_class_ref, timestamp, issuer) internal_resp = InternalResponse(auth_info=auth_info) internal_resp.set_user_id(response.get_subject().text) if "user_id_params" in self.config: user_id = "" for param in self.config["user_id_params"]: try: user_id += response.ava[param] except Exception as error: raise SATOSAAuthenticationError from error internal_resp.set_user_id(user_id) internal_resp.add_attributes( self.converter.to_internal(self.attribute_profile, response.ava)) satosa_logging( LOGGER, logging.DEBUG, "received attributes:\n%s" % json.dumps(response.ava, indent=4), state) return internal_resp
def test_auth_resp_callback_func_hashes_all_specified_attributes( self, context, satosa_config): satosa_config["INTERNAL_ATTRIBUTES"]["hash"] = ["user_id", "mail"] base = SATOSABase(satosa_config) attributes = { "user_id": ["user"], "mail": ["*****@*****.**", "*****@*****.**"] } internal_resp = InternalResponse(AuthenticationInformation("", "", "")) internal_resp.attributes = copy.copy(attributes) internal_resp.user_id = "test_user" UserIdHasher.save_state(InternalRequest(UserIdHashType.transient, ""), context.state) context.state[satosa.base.STATE_KEY] = {"requester": "test_requester"} context.state[satosa.routing. STATE_KEY] = satosa_config["FRONTEND_MODULES"][0]["name"] base._auth_resp_callback_func(context, internal_resp) for attr in satosa_config["INTERNAL_ATTRIBUTES"]["hash"]: assert internal_resp.attributes[attr] == [ UserIdHasher.hash_data(satosa_config["USER_ID_HASH_SALT"], v) for v in attributes[attr] ]
def internal_response(self): auth_info = AuthenticationInformation("auth_class_ref", "timestamp", "issuer") internal_response = InternalResponse(auth_info=auth_info) internal_response.user_id = "user1" return internal_response