def store_state(self, authn_req, relay_state, req_args): # Which page was accessed to get here came_from = geturl(self.environ) key = hash(came_from + self.environ["REMOTE_ADDR"] + str(time.time())) logger.debug("[sp.challenge] RelayState >> '%s'" % came_from) self.cache[key] = (authn_req, relay_state, req_args) return key
def store_state(self, authn_req, relay_state, req_args): # Which page was accessed to get here. came_from = geturl(self.environ) key = str(hash(came_from + self.environ["REMOTE_ADDR"] + str(time.time()))) logger.debug("[sp.challenge] RelayState >> '%s'" % came_from) self.cache[key] = (authn_req, relay_state, req_args) return key
def do(self): _cli = self.sp # Which page was accessed to get here came_from = geturl(self.environ) logger.debug("[sp.challenge] RelayState >> '%s'" % came_from) # Am I part of a virtual organization or more than one ? try: vorg_name = _cli.vorg._name except AttributeError: vorg_name = "" logger.info("[sp.challenge] VO: %s" % vorg_name) # If more than one idp and if none is selected, I have to do wayf (done, response) = self._pick_idp(came_from) # Three cases: -1 something went wrong or Discovery service used # 0 I've got an IdP to send a request to # >0 ECP in progress logger.debug("_idp_pick returned: %s" % done) if done == -1: return response elif done > 0: self.cache.outstanding_queries[done] = came_from return ECP_response(response) else: entity_id = response # Do the AuthnRequest return self._redirect_to_auth(_cli, entity_id, came_from, vorg_name="")
def not_authn(self, key, requested_authn_context): ruri = geturl(self.environ, query=False) return do_authentication(self.environ, self.start_response, authn_context=requested_authn_context, key=key, redirect_uri=ruri)
def do(self): _cli = self.sp # Which page was accessed to get here came_from = geturl(self.environ) logger.debug("[sp.challenge] RelayState >> '%s'" % came_from) # Am I part of a virtual organization or more than one ? try: vorg_name = _cli.vorg._name except AttributeError: vorg_name = "" logger.debug("[sp.challenge] VO: %s" % vorg_name) # If more than one idp and if none is selected, I have to do wayf (done, response) = self._pick_idp(came_from) # Three cases: -1 something went wrong or Discovery service used # 0 I've got an IdP to send a request to # >0 ECP in progress logger.debug("_idp_pick returned: %s" % done) if done == -1: return response(self.environ, self.start_response) elif done > 0: self.cache.outstanding_queries[done] = came_from return ECP_response(response) else: entity_id = response # Do the AuthnRequest resp = self._redirect_to_auth(_cli, entity_id, came_from, vorg_name) return resp(self.environ, self.start_response)
def not_authn(self, key, requested_authn_context): ruri = geturl(self.environ, query=False) kwargs = dict(authn_context=requested_authn_context, key=key, redirect_uri=ruri) # Clear cookie, if it already exists kaka = delete_cookie(self.environ, "idpauthn") if kaka: kwargs["headers"] = [kaka] return do_authentication(self.environ, self.start_response, **kwargs)
def do(self): _cli = self.sp # Which page was accessed to get here came_from = geturl(self.environ) logger.debug("[sp.challenge] RelayState >> '%s'" % came_from) # Am I part of a virtual organization or more than one ? try: vorg_name = _cli.vorg._name except AttributeError: vorg_name = "" logger.info("[sp.challenge] VO: %s" % vorg_name) # If more than one idp and if none is selected, I have to do wayf (done, response) = self._pick_idp(came_from) # Three cases: -1 something went wrong or Discovery service used # 0 I've got an IdP to send a request to # >0 ECP in progress logger.debug("_idp_pick returned: %s" % done) if done == -1: return response elif done > 0: self.cache.outstanding_queries[done] = came_from return ECP_response(response) else: entity_id = response # Do the AuthnRequest try: _binding, destination = _cli.pick_binding( "single_sign_on_service", self.bindings, "idpsso", entity_id=entity_id) logger.debug("binding: %s, destination: %s" % (_binding, destination)) req = _cli.create_authn_request(destination, vorg=vorg_name) _rstate = rndstr() self.cache.relay_state[_rstate] = came_from ht_args = _cli.apply_binding(_binding, "%s" % req, destination, relay_state=_rstate) _sid = req.id logger.debug("ht_args: %s" % ht_args) except Exception, exc: logger.exception(exc) resp = ServiceError( "Failed to construct the AuthnRequest: %s" % exc) return resp(self.environ, self.start_response) # remember the request self.cache.outstanding_queries[_sid] = came_from return self.response(_binding, ht_args)
def not_authn(self, key, requested_authn_context, cert_str=None, cert_key_str=None): redirect_uri = geturl(self.environ, query=False) self.logger.debug("Do authentication") auth_info = self.idphandler.authn_broker.pick(requested_authn_context) if len(auth_info): method, reference = auth_info[0] logger.debug("Authn chosen: %s (ref=%s)" % (method, reference)) return method.authenticate(self.environ, self.start_response, reference, key, redirect_uri, certificate_str=cert_str, certificate_key_str=cert_key_str) else: resp = Unauthorized("No usable authentication method") return resp(self.environ, self.start_response)
def do(self): _cli = self.sp # Which page was accessed to get here came_from = geturl(self.environ) logger.debug("[sp.challenge] RelayState >> '%s'", came_from) # If more than one idp and if none is selected, I have to do wayf (done, response) = self._pick_idp(came_from) # Three cases: -1 something went wrong or Discovery service used # 0 I've got an IdP to send a request to # >0 ECP in progress logger.debug("_idp_pick returned: %s", done) if done == -1: return response(self.environ, self.start_response) elif done > 0: self.cache.outstanding_queries[done] = came_from return ECPResponse(response) else: entity_id = response # Do the AuthnRequest resp = self.redirect_to_auth(_cli, entity_id, came_from) return resp(self.environ, self.start_response)
def _pick_idp(self, came_from): """ If more than one idp and if none is selected, I have to do wayf or disco """ _cli = self.sp logger.info("[_pick_idp] %s" % self.environ) if "HTTP_PAOS" in self.environ: if self.environ["HTTP_PAOS"] == PAOS_HEADER_INFO: if 'application/vnd.paos+xml' in self.environ["HTTP_ACCEPT"]: # Where should I redirect the user to # entityid -> the IdP to use # relay_state -> when back from authentication logger.info("- ECP client detected -") _rstate = rndstr() self.cache.relay_state[_rstate] = geturl(self.environ) _entityid = _cli.config.ecp_endpoint( self.environ["REMOTE_ADDR"]) if not _entityid: return -1, ServiceError("No IdP to talk to") logger.info("IdP to talk to: %s" % _entityid) return ecp.ecp_auth_request(_cli, _entityid, _rstate) else: return -1, ServiceError('Faulty Accept header') else: return -1, ServiceError('unknown ECP version') # Find all IdPs idps = self.sp.metadata.with_descriptor("idpsso") idp_entity_id = None # Any specific IdP specified in a query part query = self.environ.get("QUERY_STRING") if query: qdict = dict(parse_qs(query)) try: _idp_entity_id = qdict[self.idp_query_param][0] if _idp_entity_id in idps: idp_entity_id = _idp_entity_id except KeyError: logger.debug("No IdP entity ID in query: %s" % query) pass if idp_entity_id is None: if len(idps) == 1: # idps is a dictionary idp_entity_id = idps.keys()[0] elif not len(idps): return -1, ServiceError('Misconfiguration') else: logger.info("ENVIRON: %s" % self.environ) if self.wayf: if query: try: wayf_selected = dict( parse_qs(query))["wayf_selected"][0] except KeyError: return self._wayf_redirect(came_from) idp_entity_id = wayf_selected else: return self._wayf_redirect(came_from) elif self.discosrv: if query and "foo" in qdict: idp_entity_id = _cli.parse_discovery_service_response( query=query) else: sid_ = sid() SESSIONDB[sid_] = self.kwargs self.cache.outstanding_queries[sid_] = came_from logger.info("Redirect to Discovery Service function") eid = _cli.config.entityid ret = _cli.config.getattr( "endpoints", "sp")["discovery_response"][0][0] ret += "?sid=%s" % sid_ loc = _cli.create_discovery_service_request( self.discosrv, eid, **{"return": ret}) return -1, SeeOther(headers=[('Location', loc)]) else: return -1, NotImplemented("No WAYF or DS present!") logger.info("Chosen IdP: '%s'" % idp_entity_id) return 0, idp_entity_id
def _pick_idp(self, came_from): """ If more than one idp and if none is selected, I have to do wayf or disco """ _cli = self.sp logger.debug("[_pick_idp] %s", self.environ) if "HTTP_PAOS" in self.environ: if self.environ["HTTP_PAOS"] == PAOS_HEADER_INFO: if 'application/vnd.paos+xml' in self.environ["HTTP_ACCEPT"]: # Where should I redirect the user to # entityid -> the IdP to use # relay_state -> when back from authentication logger.debug("- ECP client detected -") _rstate = rndstr() self.cache.relay_state[_rstate] = geturl(self.environ) _entityid = _cli.config.ecp_endpoint( self.environ["REMOTE_ADDR"]) if not _entityid: return -1, ServiceError("No IdP to talk to") logger.debug("IdP to talk to: %s", _entityid) return ecp.ecp_auth_request(_cli, _entityid, _rstate) else: return -1, ServiceError('Faulty Accept header') else: return -1, ServiceError('unknown ECP version') # Find all IdPs idps = self.sp.metadata.with_descriptor("idpsso") idp_entity_id = None kaka = self.environ.get("HTTP_COOKIE", '') if kaka: try: (idp_entity_id, _) = parse_cookie("ve_disco", "SEED_SAW", kaka) except ValueError: pass except TypeError: pass # Any specific IdP specified in a query part query = self.environ.get("QUERY_STRING") if not idp_entity_id and query: try: _idp_entity_id = dict(parse_qs(query))[ self.idp_query_param][0] if _idp_entity_id in idps: idp_entity_id = _idp_entity_id except KeyError: logger.debug("No IdP entity ID in query: %s", query) pass if not idp_entity_id: if self.wayf: if query: try: wayf_selected = dict(parse_qs(query))[ "wayf_selected"][0] except KeyError: return self._wayf_redirect(came_from) idp_entity_id = wayf_selected else: return self._wayf_redirect(came_from) elif self.discosrv: if query: idp_entity_id = _cli.parse_discovery_service_response( query=self.environ.get("QUERY_STRING")) if not idp_entity_id: sid_ = sid() self.cache.outstanding_queries[sid_] = came_from logger.debug("Redirect to Discovery Service function") eid = _cli.config.entityid ret = _cli.config.getattr("endpoints", "sp")["discovery_response"][0][0] ret += "?sid=%s" % sid_ loc = _cli.create_discovery_service_request( self.discosrv, eid, **{"return": ret}) return -1, SeeOther(loc) elif len(idps) == 1: # idps is a dictionary idp_entity_id = idps.keys()[0] elif not len(idps): return -1, ServiceError('Misconfiguration') else: return -1, NotImplemented("No WAYF or DS present!") logger.info("Chosen IdP: '%s'", idp_entity_id) return 0, idp_entity_id
def _pick_idp(self, came_from): """ If more than one idp and if none is selected, I have to do wayf or disco """ _cli = self.sp logger.debug("[_pick_idp] %s", self.environ) if "HTTP_PAOS" in self.environ: if self.environ["HTTP_PAOS"] == PAOS_HEADER_INFO: if MIME_PAOS in self.environ["HTTP_ACCEPT"]: # Where should I redirect the user to # entityid -> the IdP to use # relay_state -> when back from authentication logger.debug("- ECP client detected -") _rstate = rndstr() self.cache.relay_state[_rstate] = geturl(self.environ) _entityid = _cli.config.ecp_endpoint( self.environ["REMOTE_ADDR"]) if not _entityid: return -1, ServiceError("No IdP to talk to") logger.debug("IdP to talk to: %s", _entityid) return ecp.ecp_auth_request(_cli, _entityid, _rstate) else: return -1, ServiceError("Faulty Accept header") else: return -1, ServiceError("unknown ECP version") # Find all IdPs idps = self.sp.metadata.with_descriptor("idpsso") idp_entity_id = None kaka = self.environ.get("HTTP_COOKIE", "") if kaka: try: (idp_entity_id, _) = parse_cookie("ve_disco", "SEED_SAW", kaka) except ValueError: pass except TypeError: pass # Any specific IdP specified in a query part query = self.environ.get("QUERY_STRING") if not idp_entity_id and query: try: _idp_entity_id = dict(parse_qs(query))[self.idp_query_param][0] if _idp_entity_id in idps: idp_entity_id = _idp_entity_id except KeyError: logger.debug("No IdP entity ID in query: %s", query) pass if not idp_entity_id: if self.wayf: if query: try: wayf_selected = dict( parse_qs(query))["wayf_selected"][0] except KeyError: return self._wayf_redirect(came_from) idp_entity_id = wayf_selected else: return self._wayf_redirect(came_from) elif self.discosrv: if query: idp_entity_id = _cli.parse_discovery_service_response( query=self.environ.get("QUERY_STRING")) if not idp_entity_id: sid_ = sid() self.cache.outstanding_queries[sid_] = came_from logger.debug("Redirect to Discovery Service function") eid = _cli.config.entityid ret = _cli.config.getattr("endpoints", "sp")["discovery_response"][0][0] ret += "?sid=%s" % sid_ loc = _cli.create_discovery_service_request( self.discosrv, eid, **{"return": ret}) return -1, SeeOther(loc) elif len(idps) == 1: # idps is a dictionary idp_entity_id = list(idps.keys())[0] elif not len(idps): return -1, ServiceError("Misconfiguration") else: return -1, NotImplemented("No WAYF or DS present!") logger.info("Chosen IdP: '%s'", idp_entity_id) return 0, idp_entity_id