def __init__(self, config_file, entityid=None, debug=False): self.urls = [] self.cache = {} self.debug = debug sp_conf = config_factory("sp", config_file) idp_conf = config_factory("idp", config_file) self.config = {"SP": sp_conf, "IDP": idp_conf} sys.path.insert(0, os.path.dirname(config_file)) conf = importlib.import_module(os.path.basename(config_file)) self.attribute_module = conf.ATTRIBUTE_MODULE # If entityID is set it means this is a proxy in front of one IdP. if entityid: self.entity_id = entityid self.sp_args = {} else: self.entity_id = None self.sp_args = {"discosrv": conf.DISCO_SRV} sp = SamlSP(None, None, self.config["SP"], self.cache, **self.sp_args) self.urls.extend(sp.register_endpoints()) idp = SamlIDP(None, None, self.config["IDP"], self.cache, None) self.urls.extend(idp.register_endpoints())
def __init__(self, config_file, entityid=None, debug=False): self.urls = [] self.cache = {} self.debug = debug sp_conf = config_factory("sp", config_file) idp_conf = config_factory("idp", config_file) self.config = { "SP": sp_conf, "IDP": idp_conf } sys.path.insert(0, os.path.dirname(config_file)) conf = importlib.import_module(os.path.basename(config_file)) self.attribute_module = conf.ATTRIBUTE_MODULE # If entityID is set it means this is a proxy in front of one IdP. if entityid: self.entity_id = entityid self.sp_args = {} else: self.entity_id = None self.sp_args = {"discosrv": conf.DISCO_SRV} sp = SamlSP(None, None, self.config["SP"], self.cache, **self.sp_args) self.urls.extend(sp.register_endpoints()) idp = SamlIDP(None, None, self.config["IDP"], self.cache, None) self.urls.extend(idp.register_endpoints())
def outgoing(self, response, instance): """ An authentication response has been received and now an authentication response from this server should be constructed. :param response: The Authentication response :param instance: SP instance that received the authentication response :return: response """ _idp = SamlIDP(instance.environ, instance.start_response, self.config["SP"], self.cache, self.outgoing) _state = instance.sp.state[response.in_response_to] orig_authn_req, relay_state, req_args = instance.sp.state[_state] # The Subject NameID. subject = response.get_subject() # Diverse arguments needed to construct the response. resp_args = _idp.idp.response_args(orig_authn_req) # TODO Slightly awkward, should be done better. _authn_info = response.authn_info()[0] # If the <AuthnContext> in the response contained one or more # <AuthenticatingAuthority> elements then use the first one, otherwise # default to using the issuer, which will be the issuing IdP. if _authn_info[1]: _authn = { "class_ref": _authn_info[0], "authn_auth": _authn_info[1][0] } else: _authn = { "class_ref": _authn_info[0], "authn_auth": response.issuer() } # This is where any possible modification of the assertion is made. try: response.ava = self.attribute_module.get_attributes(response.ava) except NoUserData as e: logger.error( "User authenticated at IdP but not found by attribute module.") raise # Will sign the response by default. resp = _idp.construct_authn_response(response.ava, name_id=subject, authn=_authn, resp_args=resp_args, relay_state=relay_state, sign_response=True) return resp
def outgoing(self, response, instance): """ An authentication response has been received and now an authentication response from this server should be constructed. :param response: The Authentication response :param instance: SP instance that received the authentication response :return: response """ _idp = SamlIDP(instance.environ, instance.start_response, self.config["SP"], self.cache, self.outgoing) _state = instance.sp.state[response.in_response_to] orig_authn_req, relay_state, req_args = instance.sp.state[_state] # The Subject NameID. subject = response.get_subject() # Diverse arguments needed to construct the response. resp_args = _idp.idp.response_args(orig_authn_req) # TODO Slightly awkward, should be done better. _authn_info = response.authn_info()[0] # If the <AuthnContext> in the response contained one or more # <AuthenticatingAuthority> elements then use the first one, otherwise # default to using the issuer, which will be the issuing IdP. if _authn_info[1]: _authn = {"class_ref": _authn_info[0], "authn_auth": _authn_info[1][0]} else: _authn = {"class_ref": _authn_info[0], "authn_auth": response.issuer()} # This is where any possible modification of the assertion is made. try: response.ava = self.attribute_module.get_attributes(response.ava) except NoUserData as e: logger.error( "User authenticated at IdP but not found by attribute module.") raise # Will sign the response by default. resp = _idp.construct_authn_response( response.ava, name_id=subject, authn=_authn, resp_args=resp_args, relay_state=relay_state, sign_response=True) return resp
def run_entity(self, spec, environ, start_response): """ Picks entity and method to run by that entity. :param spec: a tuple (entity_type, response_type, binding) :param environ: WSGI environ :param start_response: WSGI start_response :return: """ if isinstance(spec, tuple): if spec[0] == "SP": inst = SamlSP(environ, start_response, self.config["SP"], self.cache, self.outgoing, **self.sp_args) else: inst = SamlIDP(environ, start_response, self.config["IDP"], self.cache, self.incoming) func = getattr(inst, spec[1]) return func(*spec[2:]) else: return spec()