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_set_user_id(): uid = "my_id" attributes = {"attr_1": "v1", "attr_2": "v2", "attr_3": "v3"} internal_response = InternalResponse(UserIdHashType.persistent) internal_response.add_attributes(attributes) internal_response.set_user_id(uid) assert uid == internal_response.get_user_id()
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 _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 _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 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 authn_response(self, context): """ Handles the authentication response from the OP. :type context: satosa.context.Context :rtype: satosa.response.Response :param context: The context in SATOSA :return: A SATOSA response. This method is only responsible to call the callback function which generates the Response object. """ state = context.state try: state_data = state.get(self.config["state_id"]) consumer = self.get_consumer() request = context.request aresp = consumer.parse_response(AuthorizationResponse, info=json.dumps(request)) self.verify_state(aresp, state_data, state) rargs = { "code": aresp["code"], "redirect_uri": self.redirect_url, "state": state_data["state"] } atresp = consumer.do_access_token_request(request_args=rargs, state=aresp["state"]) if ("verify_accesstoken_state" not in self.config or self.config["verify_accesstoken_state"]): self.verify_state(atresp, state_data, state) user_info = self.user_information(atresp["access_token"]) internal_response = InternalResponse( auth_info=self.auth_info(request)) internal_response.add_attributes( self.converter.to_internal(self.external_type, user_info)) internal_response.set_user_id(user_info[self.user_id_attr]) if "user_id_params" in self.config: user_id = "" for param in self.config["user_id_params"]: try: user_id += user_info[param] except Exception as error: raise SATOSAAuthenticationError from error internal_response.set_user_id(user_id) context.state.remove(self.config["state_id"]) return self.auth_callback_func(context, internal_response) except Exception as error: satosa_logging(LOGGER, logging.DEBUG, "Not a valid authentication", state, exc_info=True) if isinstance(error, SATOSAError): raise error if state is not None: raise SATOSAAuthenticationError( state, "Not a valid authentication") from error raise
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 setup_for_authn_response(self, auth_req): context = Context() context.state = self.create_state(auth_req) auth_info = AuthenticationInformation(PASSWORD, "2015-09-30T12:21:37Z", "unittest_idp.xml") internal_response = InternalResponse(auth_info=auth_info) internal_response.add_attributes( DataConverter(INTERNAL_ATTRIBUTES).to_internal("saml", USERS["testuser1"])) internal_response.set_user_id(USERS["testuser1"]["eduPersonTargetedID"][0]) self.instance.provider.cdb = { "client1": {"response_types": ["id_token"], "redirect_uris": [(auth_req["redirect_uri"], None)], "client_salt": "salt"}} return context, internal_response
def authn_response(self, context): """ Handles the authentication response from the OP. :type context: satosa.context.Context :rtype: satosa.response.Response :param context: The context in SATOSA :return: A SATOSA response. This method is only responsible to call the callback function which generates the Response object. """ state = context.state try: state_data = state.get(self.config["state_id"]) consumer = self.get_consumer() request = context.request aresp = consumer.parse_response(AuthorizationResponse, info=json.dumps(request)) self.verify_state(aresp, state_data, state) rargs = {"code": aresp["code"], "redirect_uri": self.redirect_url, "state": state_data["state"]} atresp = consumer.do_access_token_request(request_args=rargs, state=aresp["state"]) if ("verify_accesstoken_state" not in self.config or self.config["verify_accesstoken_state"]): self.verify_state(atresp, state_data, state) user_info = self.user_information(atresp["access_token"]) internal_response = InternalResponse(auth_info=self.auth_info(request)) internal_response.add_attributes(self.converter.to_internal(self.external_type, user_info)) internal_response.set_user_id(user_info[self.user_id_attr]) if "user_id_params" in self.config: user_id = "" for param in self.config["user_id_params"]: try: user_id += user_info[param] except Exception as error: raise SATOSAAuthenticationError from error internal_response.set_user_id(user_id) context.state.remove(self.config["state_id"]) return self.auth_callback_func(context, internal_response) except Exception as error: satosa_logging(LOGGER, logging.DEBUG, "Not a valid authentication", state, exc_info=True) if isinstance(error, SATOSAError): raise error if state is not None: raise SATOSAAuthenticationError(state, "Not a valid authentication") from error raise
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 test_respect_sp_entity_categories(self, entity_category, expected_attributes, idp_conf, sp_conf): base = self.construct_base_url_from_entity_id(idp_conf["entityid"]) conf = {"idp_config": idp_conf, "endpoints": ENDPOINTS, "base": base, "state_id": "state_id"} internal_attributes = {attr_name: {"saml": [attr_name.lower()]} for attr_name in expected_attributes} samlfrontend = SamlFrontend(None, dict(attributes=internal_attributes), conf) samlfrontend.register_endpoints(["foo"]) idp_metadata_str = create_metadata_from_config_dict(samlfrontend.idp_config) sp_conf["metadata"]["inline"].append(idp_metadata_str) sp_conf["entity_category"] = entity_category 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) user_attributes = {k: "foo" for k in expected_attributes} user_attributes.update({k: "bar" for k in ["extra", "more", "stuff"]}) internal_response.add_attributes(user_attributes) 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 Counter(resp.ava.keys()) == Counter(expected_attributes)
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