def _authn_response(self, context): """ Handles the authentication response from the AS. :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_data = context.state[self.name] aresp = self.consumer.parse_response(AuthorizationResponse, info=json.dumps(context.request)) self._verify_state(aresp, state_data, context.state) rargs = { "code": aresp["code"], "redirect_uri": self.redirect_url, "state": state_data["state"] } atresp = self.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, context.state) user_info = self.user_information(atresp["access_token"]) internal_response = InternalData( auth_info=self.auth_info(context.request)) internal_response.attributes = self.converter.to_internal( self.external_type, user_info) internal_response.subject_id = user_info[self.user_id_attr] del context.state[self.name] return self.auth_callback_func(context, internal_response)
def _authn_response(self, context): state_data = context.state[self.name] aresp = self.consumer.parse_response(AuthorizationResponse, info=json.dumps(context.request)) self._verify_state(aresp, state_data, context.state) url = self.config['server_info']['token_endpoint'] data = dict( grant_type='authorization_code', code=aresp['code'], redirect_uri=self.redirect_url, client_id=self.config['client_config']['client_id'], client_secret=self.config['client_secret'], ) r = requests.post(url, data=data) response = r.json() if self.config.get('verify_accesstoken_state', True): self._verify_state(response, state_data, context.state) user_info = self.user_information(response["access_token"]) auth_info = self.auth_info(context.request) internal_response = InternalData(auth_info=auth_info) internal_response.attributes = self.converter.to_internal( self.external_type, user_info) internal_response.subject_id = user_info[self.user_id_attr] del context.state[self.name] return self.auth_callback_func(context, internal_response)
def internal_response(self): auth_info = AuthenticationInformation("auth_class_ref", "timestamp", "issuer") internal_response = InternalData(auth_info=auth_info) internal_response.requester = "client" internal_response.attributes = ATTRIBUTES return internal_response
def _authn_response(self, context): state_data = context.state[self.name] aresp = self.consumer.parse_response( AuthorizationResponse, info=json.dumps(context.request)) self._verify_state(aresp, state_data, context.state) url = self.config['server_info']['token_endpoint'] data = dict( grant_type='authorization_code', code=aresp['code'], redirect_uri=self.redirect_url, client_id=self.config['client_config']['client_id'], client_secret=self.config['client_secret'], ) r = requests.post(url, data=data) response = r.json() if self.config.get('verify_accesstoken_state', True): self._verify_state(response, state_data, context.state) user_info = self.user_information(response["access_token"]) auth_info = self.auth_info(context.request) internal_response = InternalData(auth_info=auth_info) internal_response.attributes = self.converter.to_internal( self.external_type, user_info) internal_response.subject_id = user_info[self.user_id_attr] del context.state[self.name] return self.auth_callback_func(context, internal_response)
def test_attributes_general(self, ldap_attribute_store): ldap_to_internal_map = (self.ldap_attribute_store_config['default'] ['ldap_to_internal_map']) for dn, attributes in self.ldap_person_records: # Mock up the internal response the LDAP attribute store is # expecting to receive. response = InternalData(auth_info=AuthenticationInformation()) # The LDAP attribute store configuration and the mock records # expect to use a LDAP search filter for the uid attribute. uid = attributes['uid'] response.attributes = {'uid': uid} context = Context() context.state = dict() ldap_attribute_store.process(context, response) # Verify that the LDAP attribute store has retrieved the mock # records from the mock LDAP server and has added the appropriate # internal attributes. for ldap_attr, ldap_value in attributes.items(): if ldap_attr in ldap_to_internal_map: internal_attr = ldap_to_internal_map[ldap_attr] response_attr = response.attributes[internal_attr] assert(ldap_value in response_attr)
def handle_response(self, context): auth_info = AuthenticationInformation("test", str(datetime.now()), "test_issuer") internal_resp = InternalData(auth_info=auth_info) internal_resp.attributes = context.request internal_resp.user_id = "test_user" return self.auth_callback_func(context, internal_resp)
def internal_request(self): req = InternalData( subject_type=NAMEID_FORMAT_PERSISTENT, requester="example_requester", ) req.attributes = FILTER + ["sn"] return req
def internal_response(self, idp_conf): auth_info = AuthenticationInformation(PASSWORD, "2015-09-30T12:21:37Z", idp_conf["entityid"]) internal_response = InternalData(auth_info=auth_info) internal_response.attributes = AttributeMapper( INTERNAL_ATTRIBUTES).to_internal("saml", USERS["testuser1"]) return internal_response
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 = InternalData(auth_info=auth_info) internal_response.attributes = AttributeMapper(INTERNAL_ATTRIBUTES).to_internal("saml", USERS["testuser1"]) internal_response.subject_id = USERS["testuser1"]["eduPersonTargetedID"][0] return internal_response
def test_perun_identity_none_user(self, mock_adapter): mock_adapter.get_perun_user.return_value = None service = self.create_perun_identity_service() service.adapter = mock_adapter resp = InternalData(auth_info=AuthenticationInformation()) resp.attributes = self.ATTRIBUTES returned_service = service.process(None, resp) assert 'perun_id' not in returned_service.attributes.keys()
def test_filter_attribute_not_in_response(self): attribute_filters = {"": {"": {"a0": "foo:bar"}}} filter_service = self.create_filter_service(attribute_filters) resp = InternalData(auth_info=AuthenticationInformation()) 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_perun_identity_test_user(self, mock_adapter): user = User(1, 'Test user') mock_adapter.get_perun_user.return_value = user service = self.create_perun_identity_service() service.adapter = mock_adapter resp = InternalData(auth_info=AuthenticationInformation()) resp.attributes = self.ATTRIBUTES returned_service = service.process(None, resp) assert 'perun_id' in returned_service.attributes.keys() assert returned_service.attributes.get('perun_id') == [user.id]
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 = InternalData(AuthenticationInformation()) 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 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 = InternalData(auth_info=AuthenticationInformation( issuer=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_auth_req_callback_stores_state_for_consent(self, context, satosa_config): base = SATOSABase(satosa_config) context.target_backend = satosa_config["BACKEND_MODULES"][0]["name"] requester_name = [{"lang": "en", "text": "Test EN"}, {"lang": "sv", "text": "Test SV"}] internal_req = InternalData( subject_type=NAMEID_FORMAT_TRANSIENT, requester_name=requester_name, ) internal_req.attributes = ["attr1", "attr2"] base._auth_req_callback_func(context, internal_req) assert context.state[consent.STATE_KEY]["requester_name"] == internal_req.requester_name assert context.state[consent.STATE_KEY]["filter"] == internal_req.attributes
def test_generate_static(self): synthetic_attributes = {"": {"default": {"a0": "value1;value2"}}} authz_service = self.create_syn_service(synthetic_attributes) resp = InternalData(auth_info=AuthenticationInformation()) resp.attributes = { "a1": ["*****@*****.**"], } ctx = Context() ctx.state = dict() authz_service.process(ctx, resp) assert ("value1" in resp.attributes['a0']) assert ("value2" in resp.attributes['a0']) assert ("*****@*****.**" in resp.attributes['a1'])
def _handle_authn_request(self, context): """ Parse and verify the authentication request into an internal request. :type context: satosa.context.Context :rtype: satosa.internal.InternalData :param context: the current context :return: the internal request """ request = urlencode(context.request) msg = "Authn req from client: {}".format(request) logline = lu.LOG_FMT.format(id=lu.get_session_id(context.state), message=msg) logger.debug(logline) try: authn_req = self.provider.parse_authentication_request(request) except InvalidAuthenticationRequest as e: msg = "Error in authn req: {}".format(str(e)) logline = lu.LOG_FMT.format(id=lu.get_session_id(context.state), message=msg) logger.error(logline) error_url = e.to_error_url() if error_url: return SeeOther(error_url) else: return BadRequest("Something went wrong: {}".format(str(e))) client_id = authn_req["client_id"] context.state[self.name] = {"oidc_request": request} subject_type = self.provider.clients[client_id].get( "subject_type", "pairwise") client_name = self.provider.clients[client_id].get("client_name") if client_name: # TODO should process client names for all languages, see OIDC Registration, Section 2.1 requester_name = [{"lang": "en", "text": client_name}] else: requester_name = None internal_req = InternalData( subject_type=subject_type, requester=client_id, requester_name=requester_name, ) internal_req.attributes = self.converter.to_internal_filter( "openid", self._get_approved_attributes( self.provider.configuration_information["claims_supported"], authn_req)) return internal_req
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 = InternalData(auth_info=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"] base._auth_resp_callback_func(context, internal_resp) expected_user_id = "*****@*****.**" assert internal_resp.subject_id == expected_user_id
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 = InternalData(auth_info=AuthenticationInformation()) resp.attributes = { "a0": ["foo3"], } try: ctx = Context() ctx.state = dict() authz_service.process(ctx, resp) except SATOSAAuthenticationError as ex: assert False
def test_generate_static(self): synthetic_attributes = { "": { "default": {"a0": "value1;value2" }} } authz_service = self.create_syn_service(synthetic_attributes) resp = InternalData(auth_info=AuthenticationInformation()) resp.attributes = { "a1": ["*****@*****.**"], } ctx = Context() ctx.state = dict() authz_service.process(ctx, resp) assert("value1" in resp.attributes['a0']) assert("value2" in resp.attributes['a0']) assert("*****@*****.**" in resp.attributes['a1'])
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 = InternalData(auth_info=AuthenticationInformation()) resp.attributes = { "a0": ["foo3"], } try: ctx = Context() ctx.state = dict() authz_service.process(ctx, resp) except SATOSAAuthenticationError as ex: assert False
def test_generate_mustache2(self): synthetic_attributes = { "": { "default": {"a0": "{{kaka.first}}#{{eppn.scope}}" }} } authz_service = self.create_syn_service(synthetic_attributes) resp = InternalData(auth_info=AuthenticationInformation()) resp.attributes = { "kaka": ["kaka1","kaka2"], "eppn": ["*****@*****.**","*****@*****.**"] } ctx = Context() ctx.state = dict() authz_service.process(ctx, resp) assert("kaka1#example.com" in resp.attributes['a0']) assert("kaka1" in resp.attributes['kaka']) assert("*****@*****.**" in resp.attributes['eppn']) assert("*****@*****.**" in resp.attributes['eppn'])
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 = InternalData(auth_info=AuthenticationInformation("", "", "")) internal_resp.attributes = copy.copy(attributes) internal_resp.subject_id = "test_user" 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] == [ util.hash_data(satosa_config.get("USER_ID_HASH_SALT", ""), v) for v in attributes[attr] ]
def _translate_response(self, response, issuer): """ Translates oidc response to SATOSA internal response. :type response: dict[str, str] :type issuer: str :type subject_type: str :rtype: InternalData :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. """ auth_info = AuthenticationInformation(UNSPECIFIED, str(datetime.now()), issuer) internal_resp = InternalData(auth_info=auth_info) internal_resp.attributes = self.converter.to_internal("openid", response) internal_resp.subject_id = response["sub"] return internal_resp
def _handle_authn_request(self, context): """ Parse and verify the authentication request into an internal request. :type context: satosa.context.Context :rtype: satosa.internal.InternalData :param context: the current context :return: the internal request """ request = urlencode(context.request) satosa_logging(logger, logging.DEBUG, "Authn req from client: {}".format(request), context.state) try: authn_req = self.provider.parse_authentication_request(request) except InvalidAuthenticationRequest as e: satosa_logging(logger, logging.ERROR, "Error in authn req: {}".format(str(e)), context.state) error_url = e.to_error_url() if error_url: return SeeOther(error_url) else: return BadRequest("Something went wrong: {}".format(str(e))) client_id = authn_req["client_id"] context.state[self.name] = {"oidc_request": request} subject_type = self.provider.clients[client_id].get("subject_type", "pairwise") client_name = self.provider.clients[client_id].get("client_name") if client_name: # TODO should process client names for all languages, see OIDC Registration, Section 2.1 requester_name = [{"lang": "en", "text": client_name}] else: requester_name = None internal_req = InternalData( subject_type=subject_type, requester=client_id, requester_name=requester_name, ) internal_req.attributes = self.converter.to_internal_filter( "openid", self._get_approved_attributes(self.provider.configuration_information["claims_supported"], authn_req)) return internal_req
def test_attribute_policy(self): requester = "requester" attribute_policies = { "attribute_policy": { "requester_everything_allowed": {}, "requester_nothing_allowed": { "allowed": {} }, "requester_subset_allowed": { "allowed": { "attr1", "attr2", }, }, }, } attributes = { "attr1": ["foo"], "attr2": ["foo", "bar"], "attr3": ["foo"] } results = { "requester_everything_allowed": attributes.keys(), "requester_nothing_allowed": set(), "requester_subset_allowed": {"attr1", "attr2"}, } for requester, result in results.items(): attribute_policy_service = self.create_attribute_policy_service( attribute_policies) ctx = Context() ctx.state = dict() resp = InternalData(auth_info=AuthenticationInformation()) resp.requester = requester resp.attributes = { "attr1": ["foo"], "attr2": ["foo", "bar"], "attr3": ["foo"] } filtered = attribute_policy_service.process(ctx, resp) assert (filtered.attributes.keys() == result)
def test_generate_mustache_empty_attribute(self): synthetic_attributes = { "": { "default": { "a0": "{{kaka.first}}#{{eppn.scope}}" } } } authz_service = self.create_syn_service(synthetic_attributes) resp = InternalData(auth_info=AuthenticationInformation()) resp.attributes = { "kaka": ["kaka1", "kaka2"], "eppn": None, } ctx = Context() ctx.state = dict() authz_service.process(ctx, resp) assert ("kaka1#" in resp.attributes['a0']) assert ("kaka1" in resp.attributes['kaka']) assert ("kaka2" in resp.attributes['kaka'])
def test_generate_mustache1(self): synthetic_attributes = { "": { "default": { "a0": "{{kaka}}#{{eppn.scope}}" } } } authz_service = self.create_syn_service(synthetic_attributes) resp = InternalData(auth_info=AuthenticationInformation()) resp.attributes = { "kaka": ["kaka1"], "eppn": ["*****@*****.**", "*****@*****.**"] } ctx = Context() ctx.state = dict() authz_service.process(ctx, resp) assert ("kaka1#example.com" in resp.attributes['a0']) assert ("kaka1" in resp.attributes['kaka']) assert ("*****@*****.**" in resp.attributes['eppn']) assert ("*****@*****.**" in resp.attributes['eppn'])
def _authn_response(self, context): aresp = self.consumer.parse_response( AuthorizationResponse, info=json.dumps(context.request)) url = self.config['server_info']['token_endpoint'] data = dict( grant_type='authorization_code', code=aresp['code'], redirect_uri=self.redirect_url, client_id=self.config['client_config']['client_id'], client_secret=self.config['client_secret'], ) headers = {'Accept': 'application/json'} r = requests.post(url, data=data, headers=headers) response = r.json() token = response['access_token'] orcid, name = response['orcid'], response['name'] user_info = self.user_information(token, orcid, name) auth_info = self.auth_info(context.request) internal_response = InternalData(auth_info=auth_info) internal_response.attributes = self.converter.to_internal( self.external_type, user_info) internal_response.subject_id = orcid return self.auth_callback_func(context, internal_response)
def test_filter_all_attributes_from_all_target_providers_for_all_requesters( self): attribute_filters = { "": { # all providers "": { # all requesters "": "foo:bar" # all attributes } } } filter_service = self.create_filter_service(attribute_filters) resp = InternalData(auth_info=AuthenticationInformation()) resp.attributes = { "a1": ["abc:xyz"], "a2": ["foo:bar", "1:foo:bar:2"], "a3": ["a:foo:bar:b"] } filtered = filter_service.process(None, resp) assert filtered.attributes == { "a1": [], "a2": ["foo:bar", "1:foo:bar:2"], "a3": ["a:foo:bar:b"] }
def _authn_response(self, context): state_data = context.state[self.name] aresp = self.consumer.parse_response(AuthorizationResponse, info=json.dumps(context.request)) self._verify_state(aresp, state_data, context.state) rargs = { "code": aresp["code"], "redirect_uri": self.redirect_url, "state": state_data["state"] } atresp = self.consumer.do_access_token_request(request_args=rargs, state=aresp['state']) user_info = self.user_information(atresp['access_token'], atresp['orcid'], atresp['name']) internal_response = InternalData( auth_info=self.auth_info(context.request)) internal_response.attributes = self.converter.to_internal( self.external_type, user_info) internal_response.subject_id = user_info[self.user_id_attr] del context.state[self.name] return self.auth_callback_func(context, internal_response)
def _authn_response(self, context): aresp = self.consumer.parse_response(AuthorizationResponse, info=json.dumps(context.request)) url = self.config['server_info']['token_endpoint'] data = dict( grant_type='authorization_code', code=aresp['code'], redirect_uri=self.redirect_url, client_id=self.config['client_config']['client_id'], client_secret=self.config['client_secret'], ) headers = {'Accept': 'application/json'} r = requests.post(url, data=data, headers=headers) response = r.json() token = response['access_token'] orcid, name = response['orcid'], response['name'] user_info = self.user_information(token, orcid, name) auth_info = self.auth_info(context.request) internal_response = InternalData(auth_info=auth_info) internal_response.attributes = self.converter.to_internal( self.external_type, user_info) internal_response.subject_id = orcid return self.auth_callback_func(context, internal_response)
def internal_response(self, idp_conf): auth_info = AuthenticationInformation(PASSWORD, "2015-09-30T12:21:37Z", idp_conf["entityid"]) internal_response = InternalData(auth_info=auth_info) internal_response.attributes = AttributeMapper(INTERNAL_ATTRIBUTES).to_internal("saml", USERS["testuser1"]) return internal_response
def _handle_authn_request(self, context, binding_in, idp): """ See doc for handle_authn_request method. :type context: satosa.context.Context :type binding_in: str :type idp: saml.server.Server :rtype: satosa.response.Response :param context: The current context :param binding_in: The pysaml binding type :param idp: The saml frontend idp server :return: response """ req_info = idp.parse_authn_request(context.request["SAMLRequest"], binding_in) authn_req = req_info.message satosa_logging(logger, logging.DEBUG, "%s" % authn_req, context.state) try: resp_args = idp.response_args(authn_req) except SAMLError as e: satosa_logging( logger, logging.ERROR, "Could not find necessary info about entity: %s" % e, context.state) return ServiceError("Incorrect request from requester: %s" % e) requester = resp_args["sp_entity_id"] context.state[self.name] = self._create_state_data( context, idp.response_args(authn_req), context.request.get("RelayState")) subject = authn_req.subject name_id_value = subject.name_id.text if subject else None nameid_formats = { "from_policy": authn_req.name_id_policy and authn_req.name_id_policy.format, "from_response": subject and subject.name_id and subject.name_id.format, "from_metadata": (idp.metadata[requester].get("spsso_descriptor", [{}])[0].get("name_id_format", [{}])[0].get("text")), "default": NAMEID_FORMAT_TRANSIENT, } name_id_format = ( nameid_formats["from_policy"] or (nameid_formats["from_response"] != NAMEID_FORMAT_UNSPECIFIED and nameid_formats["from_response"]) or nameid_formats["from_metadata"] or nameid_formats["from_response"] or nameid_formats["default"]) requester_name = self._get_sp_display_name(idp, requester) internal_req = InternalData( subject_id=name_id_value, subject_type=name_id_format, requester=requester, requester_name=requester_name, ) idp_policy = idp.config.getattr("policy", "idp") if idp_policy: internal_req.attributes = self._get_approved_attributes( idp, idp_policy, requester, context.state) return self.auth_req_callback_func(context, internal_req)
def handle_response(self, context): auth_info = AuthenticationInformation("test", str(datetime.now()), "test_issuer") internal_resp = InternalData(auth_info=auth_info) internal_resp.attributes = context.request internal_resp.user_id = "test_user" return self.auth_callback_func(context, internal_resp)
def _handle_authn_request(self, context, binding_in, idp): """ See doc for handle_authn_request method. :type context: satosa.context.Context :type binding_in: str :type idp: saml.server.Server :rtype: satosa.response.Response :param context: The current context :param binding_in: The pysaml binding type :param idp: The saml frontend idp server :return: response """ req_info = idp.parse_authn_request(context.request["SAMLRequest"], binding_in) authn_req = req_info.message satosa_logging(logger, logging.DEBUG, "%s" % authn_req, context.state) try: resp_args = idp.response_args(authn_req) except SAMLError as e: satosa_logging(logger, logging.ERROR, "Could not find necessary info about entity: %s" % e, context.state) return ServiceError("Incorrect request from requester: %s" % e) requester = resp_args["sp_entity_id"] context.state[self.name] = self._create_state_data(context, idp.response_args(authn_req), context.request.get("RelayState")) subject = authn_req.subject name_id_value = subject.name_id.text if subject else None nameid_formats = { "from_policy": authn_req.name_id_policy and authn_req.name_id_policy.format, "from_response": subject and subject.name_id and subject.name_id.format, "from_metadata": ( idp.metadata[requester] .get("spsso_descriptor", [{}])[0] .get("name_id_format", [{}])[0] .get("text") ), "default": NAMEID_FORMAT_TRANSIENT, } name_id_format = ( nameid_formats["from_policy"] or ( nameid_formats["from_response"] != NAMEID_FORMAT_UNSPECIFIED and nameid_formats["from_response"] ) or nameid_formats["from_metadata"] or nameid_formats["from_response"] or nameid_formats["default"] ) requester_name = self._get_sp_display_name(idp, requester) internal_req = InternalData( subject_id=name_id_value, subject_type=name_id_format, requester=requester, requester_name=requester_name, ) idp_policy = idp.config.getattr("policy", "idp") if idp_policy: internal_req.attributes = self._get_approved_attributes( idp, idp_policy, requester, context.state ) return self.auth_req_callback_func(context, internal_req)
def _handle_authn_request(self, context, binding_in, idp): """ See doc for handle_authn_request method. :type context: satosa.context.Context :type binding_in: str :type idp: saml.server.Server :rtype: satosa.response.Response :param context: The current context :param binding_in: The pysaml binding type :param idp: The saml frontend idp server :return: response """ req_info = idp.parse_authn_request(context.request["SAMLRequest"], binding_in) authn_req = req_info.message msg = "{}".format(authn_req) logline = lu.LOG_FMT.format(id=lu.get_session_id(context.state), message=msg) logger.debug(logline) # keep the ForceAuthn value to be used by plugins context.decorate(Context.KEY_FORCE_AUTHN, authn_req.force_authn) try: resp_args = idp.response_args(authn_req) except SAMLError as e: msg = "Could not find necessary info about entity: {}".format(e) logline = lu.LOG_FMT.format(id=lu.get_session_id(context.state), message=msg) logger.error(logline) return ServiceError("Incorrect request from requester: %s" % e) requester = resp_args["sp_entity_id"] context.state[self.name] = self._create_state_data(context, idp.response_args(authn_req), context.request.get("RelayState")) subject = authn_req.subject name_id_value = subject.name_id.text if subject else None nameid_formats = { "from_policy": authn_req.name_id_policy and authn_req.name_id_policy.format, "from_response": subject and subject.name_id and subject.name_id.format, "from_metadata": ( idp.metadata[requester] .get("spsso_descriptor", [{}])[0] .get("name_id_format", [{}])[0] .get("text") ), "default": NAMEID_FORMAT_TRANSIENT, } name_id_format = ( nameid_formats["from_policy"] or ( nameid_formats["from_response"] != NAMEID_FORMAT_UNSPECIFIED and nameid_formats["from_response"] ) or nameid_formats["from_metadata"] or nameid_formats["from_response"] or nameid_formats["default"] ) requester_name = self._get_sp_display_name(idp, requester) internal_req = InternalData( subject_id=name_id_value, subject_type=name_id_format, requester=requester, requester_name=requester_name, ) idp_policy = idp.config.getattr("policy", "idp") if idp_policy: internal_req.attributes = self._get_approved_attributes( idp, idp_policy, requester, context.state ) authn_context_class_ref_nodes = getattr( authn_req.requested_authn_context, 'authn_context_class_ref', [] ) authn_context = [ref.text for ref in authn_context_class_ref_nodes] context.decorate(Context.KEY_AUTHN_CONTEXT_CLASS_REF, authn_context) context.decorate(Context.KEY_METADATA_STORE, self.idp.metadata) return self.auth_req_callback_func(context, internal_req)
def _handle_authn_request(self, context, binding_in, idp): """ See doc for handle_authn_request method. :type context: satosa.context.Context :type binding_in: str :type idp: saml.server.Server :rtype: satosa.response.Response :param context: The current context :param binding_in: The pysaml binding type :param idp: The saml frontend idp server :return: response """ req_info = idp.parse_authn_request(context.request["SAMLRequest"], binding_in) authn_req = req_info.message satosa_logging(logger, logging.DEBUG, "%s" % authn_req, context.state) try: resp_args = idp.response_args(authn_req) except SAMLError as e: satosa_logging( logger, logging.ERROR, "Could not find necessary info about entity: %s" % e, context.state) return ServiceError("Incorrect request from requester: %s" % e) requester = resp_args["sp_entity_id"] context.state[self.name] = self._create_state_data( context, idp.response_args(authn_req), context.request.get("RelayState")) if authn_req.name_id_policy and authn_req.name_id_policy.format: name_format = authn_req.name_id_policy.format else: # default to name id format from metadata, or just transient name id name_format_from_metadata = idp.metadata[requester][ "spsso_descriptor"][0].get("name_id_format") if name_format_from_metadata: name_format = name_format_from_metadata[0]["text"] else: name_format = NAMEID_FORMAT_TRANSIENT subject = authn_req.subject subject_id = subject.name_id.text if subject else None # XXX should subject.name_id.format overwrite name_id_policy.format? subject_type = subject.name_id.format if subject else name_format requester_name = self._get_sp_display_name(idp, requester) internal_req = InternalData( subject_id=subject_id, subject_type=subject_type, requester=requester, requester_name=requester_name, ) idp_policy = idp.config.getattr("policy", "idp") if idp_policy: internal_req.attributes = self._get_approved_attributes( idp, idp_policy, requester, context.state) return self.auth_req_callback_func(context, internal_req)