def response(self, binding, http_args): resp = None if binding == BINDING_HTTP_ARTIFACT: resp = Redirect() elif http_args["data"]: resp = Response(http_args["data"], headers=http_args["headers"]) else: for header in http_args["headers"]: if header[0] == "Location": resp = Redirect(header[1]) if not resp: resp = ServiceError("Don't know how to return response") return resp(self.environ, self.start_response)
def slo(environ, start_response, user): # so here I might get either a LogoutResponse or a LogoutRequest client = environ['repoze.who.plugins']["saml2auth"] sc = client.saml_client if "QUERY_STRING" in environ: query = parse_qs(environ["QUERY_STRING"]) logger.info("query: %s" % query) try: response = sc.parse_logout_request_response( query["SAMLResponse"][0], binding=BINDING_HTTP_REDIRECT) if response: logger.info("LOGOUT response parsed OK") except KeyError: # return error reply response = None if response is None: request = sc.lo headers = [] delco = delete_cookie(environ, "pysaml2") if delco: headers.append(delco) resp = Redirect("/done", headers=headers) return resp(environ, start_response)
def verify(self, request, **kwargs): """ Verifies that the given username and password was correct :param request: Either the query part of a URL a urlencoded body of a HTTP message or a parse such. :param kwargs: Catch whatever else is sent. :return: redirect back to where ever the base applications wants the user after authentication. """ #logger.debug("verify(%s)" % request) if isinstance(request, six.string_types): _dict = parse_qs(request) elif isinstance(request, dict): _dict = request else: raise ValueError("Wrong type of input") # verify username and password try: self._verify(_dict["password"][0], _dict["login"][0]) timestamp = str(int(time.mktime(time.gmtime()))) msg = "::".join([_dict["login"][0], timestamp]) info = self.symmetric.encrypt(msg.encode()) self.active[info] = timestamp cookie = make_cookie(self.cookie_name, info, self.srv.seed) return_to = create_return_url(self.return_to, _dict["query"][0], **{self.query_param: "true"}) resp = Redirect(return_to, headers=[cookie]) except (ValueError, KeyError): resp = Unauthorized("Unknown user or wrong password") return resp
def do_verify(environ, start_response, _): query = parse_qs(get_post(environ)) logger.debug("do_verify: %s", query) try: _ok, user = verify_username_and_password(query) except KeyError: _ok = False user = None if not _ok: resp = Unauthorized("Unknown user or wrong password") else: uid = rndstr(24) IDP.cache.uid2user[uid] = user IDP.cache.user2uid[user] = uid logger.debug("Register %s under '%s'", user, uid) kaka = set_cookie("idpauthn", "/", uid, query["authn_reference"][0]) lox = "%s?id=%s&key=%s" % (query["redirect_uri"][0], uid, query["key"][0]) logger.debug("Redirect => %s", lox) resp = Redirect(lox, headers=[kaka], content="text/html") return resp(environ, start_response)
def setup_idp(self, user, reference, redirect_uri, key): uid = rndstr(24) self.idphandler.idp_server.cache.uid2user[uid] = user self.idphandler.idp_server.cache.user2uid[user] = uid logger.debug("Register %s under '%s'" % (user, uid)) cookie = self.idphandler.set_authorization_cookie(uid, reference) lox = "%s?id=%s&key=%s" % (redirect_uri, uid, key) logger.debug("Redirect => %s" % lox) resp = Redirect(lox, headers=[cookie], content="text/html") return resp
def do(self, response, binding, relay_state="", mtype="response"): """ :param response: The SAML response, transport encoded :param binding: Which binding the query came in over """ # tmp_outstanding_queries = dict(self.outstanding_queries) if not response: logger.info("Missing Response") resp = Unauthorized('Unknown user') return resp(self.environ, self.start_response) try: conv_info = { 'remote_addr': self.environ['REMOTE_ADDR'], 'request_uri': self.environ['REQUEST_URI'], 'entity_id': self.sp.config.entityid, 'endpoints': self.sp.config.getattr('endpoints', 'sp') } self.response = self.sp.parse_authn_request_response( response, binding, self.outstanding_queries, self.cache.outstanding_certs, conv_info=conv_info) except UnknownPrincipal as excp: logger.error("UnknownPrincipal: %s", excp) resp = ServiceError("UnknownPrincipal: %s" % (excp, )) return resp(self.environ, self.start_response) except UnsupportedBinding as excp: logger.error("UnsupportedBinding: %s", excp) resp = ServiceError("UnsupportedBinding: %s" % (excp, )) return resp(self.environ, self.start_response) except VerificationError as err: resp = ServiceError("Verification error: %s" % (err, )) return resp(self.environ, self.start_response) except SignatureError as err: resp = ServiceError("Signature error: %s" % (err, )) return resp(self.environ, self.start_response) except Exception as err: resp = ServiceError("Other error: %s" % (err, )) return resp(self.environ, self.start_response) logger.info("AVA: %s", self.response.ava) user = User(self.response.name_id, self.response.ava, self.response) cookie = self.cache.set_cookie(user) resp = Redirect("/", headers=[ cookie, ]) return resp(self.environ, self.start_response)
def construct_authn_response(self, idp, state, identity, name_id, authn, resp_args, relay_state, sign_response=True): """ Constructs an auth response :type idp: saml.server.Server :type state: satosa.state.State :type identity: dict[str, str] :type name_id: saml2.saml.NameID :type authn: dict[str, str] :type resp_args: dict[str, str] :type relay_state: str :type sign_response: bool :param idp: The saml frontend idp server :param state: The current state :param identity: Information about an user (The ava attributes) :param name_id: The name id :param authn: auth info :param resp_args: response arguments :param relay_state: the relay state :param sign_response: Flag for signing the response or not :return: The constructed response """ _resp = idp.create_authn_response(identity, name_id=name_id, authn=authn, sign_response=sign_response, **resp_args) http_args = idp.apply_binding( resp_args["binding"], "%s" % _resp, resp_args["destination"], relay_state, response=True) satosa_logging(LOGGER, logging.DEBUG, "HTTPargs: %s" % http_args, state) resp = None if http_args["data"]: resp = Response(http_args["data"], headers=http_args["headers"]) else: for header in http_args["headers"]: if header[0] == "Location": resp = Redirect(header[1]) if not resp: msg = "Don't know how to return response" satosa_logging(LOGGER, logging.ERROR, msg, state) resp = ServiceError(msg) return resp
def slo_redirect_or_post(self, query, binding): log.debug("Query: " + query) log.debug("Binding: " + binding) try: req_info = self.parse_logout_request(query, binding) except Exception as exc: log.exception("Message parsing failed.") return BadRequest("Message parsing failed") msg = req_info.message if msg.name_id: lid = self.ident.find_local_id(msg.name_id) if lid in self.cache.user2uid: uid = self.cache.user2uid[lid] if uid in self.cache.uid2user: del self.cache.uid2user[uid] del self.cache.user2uid[lid] try: self.session_db.remove_authn_statements(msg.name_id) except KeyError as exc: log.exception("Session removal failed") resp = self.create_logout_response(msg, [binding]) binding, destination = self.pick_binding("single_logout_service", [binding], "spsso", req_info) response = True try: hinfo = self.apply_binding(binding, "%s" % resp, destination, query['relay_state'], response=response) except Exception as exc: log.exception("ServiceError: %s", exc) return ServiceError("%s" % exc) if binding == BINDING_HTTP_REDIRECT: for key, value in hinfo["headers"]: if key.lower() == "location": return Redirect(value, headers=hinfo["headers"]) return ServiceError("missing Location header") else: return Response(hinfo["data"], headers=hinfo["headers"])
def response(self, binding, http_args, do_not_start_response=False): if binding == BINDING_HTTP_ARTIFACT: resp = Redirect() elif binding == BINDING_HTTP_REDIRECT: for param, value in http_args["headers"]: if param == "Location": resp = SeeOther(str(value)) break else: resp = ServiceError("Parameter error") else: resp = Response(http_args["data"], headers=http_args["headers"]) if do_not_start_response: return resp else: return resp(self.environ, self.start_response)
def verify(self, environ, start_response): session = Session(environ) if self.MUTLIPLEAUTHENTICATIONCOUNTER in session: authn_method = session[self.MUTLIPLEAUTHENTICATIONCOUNTER] if authn_method > (self.auth_list_lengt - 1) or self.auth_list_lengt == 0: resp = Unauthorized("No authentication method") elif authn_method == (self.auth_list_lengt - 1): return self.auth_list[authn_method].verify(environ, start_response) else: _ok = self.auth_list[authn_method].verify_bool(environ, start_response) if _ok: session[self.MUTLIPLEAUTHENTICATIONCOUNTER] = authn_method + 1 resp = Redirect(session[self.MULTIPLEAUTHENTICATIONREDIRECT]) else: return self.auth_list[authn_method].verify(environ, start_response) else: resp = Unauthorized("No authentication method") return resp(environ, start_response)
def construct_authn_response(self, identity, name_id, authn, resp_args, relay_state, sign_response=True): """ :param identity: :param name_id: :param authn: :param resp_args: :param relay_state: :param sign_response: :return: """ _resp = self.idp.create_authn_response(identity, name_id=name_id, authn=authn, sign_response=sign_response, **resp_args) http_args = self.idp.apply_binding(resp_args["binding"], "%s" % _resp, resp_args["destination"], relay_state, response=True) logger.debug("HTTPargs: %s" % http_args) resp = None if http_args["data"]: resp = Response(http_args["data"], headers=http_args["headers"]) else: for header in http_args["headers"]: if header[0] == "Location": resp = Redirect(header[1]) if not resp: resp = ServiceError("Don't know how to return response") return resp(self.environ, self.start_response)
def authn_response(server_env, req_info, userid, identity, authn=None, authn_decl=None, service=""): # base 64 encoded request logger.debug("User info: %s" % identity) if service: issuer = "%s%s" % (server_env["base_url"], service) else: issuer = None logger.info("ISSUER: %s" % issuer) _idp = server_env["idp"] binding, destination = _idp.pick_binding("assertion_consumer_service", entity_id=req_info.sender()) logger.debug("binding: %s, destination: %s" % (binding, destination)) authn_resp = _idp.create_authn_response(identity, req_info.message.id, destination, req_info.sender(), req_info.message.name_id_policy, str(userid), authn=authn, sign_assertion=server_env["SIGN"], authn_decl=authn_decl, issuer=issuer) logger.info("LOGIN success: sp_entity_id=%s#authn=%s" % (req_info.sender(), authn)) logger.debug("AuthNResponse: %s" % authn_resp) ht_args = _idp.apply_binding(binding, "%s" % authn_resp, destination, req_info.relay_state, response=True) logger.debug("ht_args: %s" % ht_args) if "status" in ht_args and ht_args["status"] == 302: return Redirect(ht_args["data"], headers=ht_args["headers"]) else: return Response(ht_args["data"], headers=ht_args["headers"])
def logout(environ, start_response, user): # This is where it starts when a user wants to log out client = environ['repoze.who.plugins']["saml2auth"] subject_id = environ["repoze.who.identity"]['repoze.who.userid'] logger.info("[logout] subject_id: '%s'" % (subject_id, )) target = "/done" # What if more than one _dict = client.saml_client.global_logout(subject_id) logger.info("[logout] global_logout > %s" % (_dict, )) rem = environ['repoze.who.plugins'][client.rememberer_name] rem.forget(environ, subject_id) for key, item in _dict.items(): if isinstance(item, tuple): binding, htargs = item else: # result from logout, should be OK pass resp = Redirect("Successful Logout", headers=[("Location", target)]) return resp(environ, start_response)
def do(self, response, binding, relay_state="", mtype="response"): """ :param response: The SAML response, transport encoded :param binding: Which binding the query came in over """ #tmp_outstanding_queries = dict(self.outstanding_queries) if not response: logger.info("Missing Response") resp = Unauthorized('Unknown user') return resp(self.environ, self.start_response) try: self.response = self.sp.parse_authn_request_response( response, binding, self.outstanding_queries, self.cache.outstanding_certs) except UnknownPrincipal as excp: logger.error("UnknownPrincipal: %s" % (excp, )) resp = ServiceError("UnknownPrincipal: %s" % (excp, )) return resp(self.environ, self.start_response) except UnsupportedBinding as excp: logger.error("UnsupportedBinding: %s" % (excp, )) resp = ServiceError("UnsupportedBinding: %s" % (excp, )) return resp(self.environ, self.start_response) except VerificationError as err: resp = ServiceError("Verification error: %s" % (err, )) return resp(self.environ, self.start_response) except Exception as err: resp = ServiceError("Other error: %s" % (err, )) return resp(self.environ, self.start_response) logger.info("AVA: %s" % self.response.ava) user = User(self.response.name_id, self.response.ava) cookie = self.cache.set_cookie(user) resp = Redirect("/", headers=[ ("Location", "/"), cookie, ]) return resp(self.environ, self.start_response)
def authenticate(self, environ, start_response, reference, key, redirect_uri, **kwargs): _sid = "" _encrypt_sid = "" if "certificate_str" in kwargs and kwargs[ "certificate_str"] is not None: _sid = self.sphandler.add_certificate_to_cache( kwargs["certificate_str"]) if "certificate_key_str" in kwargs and kwargs[ "certificate_key_str"] is not None: _encrypt_sid = self.sphandler.add_certificate_to_cache( kwargs["certificate_key_str"]) query_dict = { "key": key, "authn_reference": reference, "redirect_uri": redirect_uri } f = {'query': self.encrypt_dict(query_dict)} urllib.urlencode(f) query = "/" + self.idphandler.IDP_VERIFY_URL + "?" + urllib.urlencode( f) cookie_load = { "query": query, "sid": _sid, "encrypt_sid": _encrypt_sid } cookie_load = self.encrypt_dict(cookie_load) cookie = self.idphandler.set_cookie(self.SPAUTHENTICATIONCOOKIE, "/", cookie_load) resp = Redirect("/" + self.sphandler.sp_conf.SPVERIFYBASEIDP, headers=[cookie]) return resp(environ, start_response)
def logout(environ, start_response, sp): user = CACHE.get_user(environ) if user is None: sso = SSO(sp, environ, start_response, cache=CACHE, **ARGS) return sso.do() logger.info("[logout] subject_id: '%s'", user.name_id) # What if more than one data = sp.global_logout(user.name_id) logger.info("[logout] global_logout > %s", data) for entity_id, logout_info in data.items(): if isinstance(logout_info, tuple): binding, http_info = logout_info if binding == BINDING_HTTP_POST: body = "".join(http_info["data"]) resp = Response(body) return resp(environ, start_response) elif binding == BINDING_HTTP_REDIRECT: for key, value in http_info["headers"]: if key.lower() == "location": resp = Redirect(value) return resp(environ, start_response) resp = ServiceError("missing Location header") return resp(environ, start_response) else: resp = ServiceError("unknown logout binding: %s", binding) return resp(environ, start_response) else: # result from logout, should be OK pass return finish_logout(environ, start_response)
def authn_redirect(self, environ): cookie_dict = self.sp_auth_cookie(environ) return Redirect(cookie_dict["query"])
def do(self, request, binding, relay_state="", encrypt_cert=None, **kwargs): logger.info("--- Single Log Out Service ---") try: logger.debug("req: '%s'", request) req_info = IDP.parse_logout_request(request, binding) except Exception as exc: logger.error("Bad request: %s", exc) resp = BadRequest("%s" % exc) return resp(self.environ, self.start_response) msg = req_info.message if msg.name_id: lid = IDP.ident.find_local_id(msg.name_id) logger.info("local identifier: %s", lid) if lid in IDP.cache.user2uid: uid = IDP.cache.user2uid[lid] if uid in IDP.cache.uid2user: del IDP.cache.uid2user[uid] del IDP.cache.user2uid[lid] # remove the authentication try: IDP.session_db.remove_authn_statements(msg.name_id) except KeyError as exc: logger.error("Unknown session: %s", exc) resp = ServiceError("Unknown session: %s", exc) return resp(self.environ, self.start_response) resp = IDP.create_logout_response(msg, [binding]) if binding == BINDING_SOAP: destination = "" response = False else: binding, destination = IDP.pick_binding("single_logout_service", [binding], "spsso", req_info) response = True try: hinfo = IDP.apply_binding(binding, "%s" % resp, destination, relay_state, response=response) except Exception as exc: logger.error("ServiceError: %s", exc) resp = ServiceError("%s" % exc) return resp(self.environ, self.start_response) #_tlh = dict2list_of_tuples(hinfo["headers"]) delco = delete_cookie(self.environ, "idpauthn") if delco: hinfo["headers"].append(delco) logger.info("Header: %s", (hinfo["headers"], )) if binding == BINDING_HTTP_REDIRECT: for key, value in hinfo['headers']: if key.lower() == 'location': resp = Redirect(value, headers=hinfo["headers"]) return resp(self.environ, self.start_response) resp = ServiceError('missing Location header') return resp(self.environ, self.start_response) else: resp = Response(hinfo["data"], headers=hinfo["headers"]) return resp(self.environ, self.start_response)
resp = ServiceError("UnsupportedBinding: %s" % (excp,)) return resp(self.environ, self.start_response) except VerificationError, err: resp = ServiceError("Verification error: %s" % (err,)) return resp(self.environ, self.start_response) except Exception, err: resp = ServiceError("Other error: %s" % (err,)) return resp(self.environ, self.start_response) logger.info("AVA: %s" % self.response.ava) user = User(self.response.name_id, self.response.ava) cookie = self.cache.set_cookie(user) resp = Redirect("/", headers=[ ("Location", "/"), cookie, ]) return resp(self.environ, self.start_response) def verify_attributes(self, ava): logger.info("SP: %s" % self.sp.config.entityid) rest = POLICY.get_entity_categories( self.sp.config.entityid, self.sp.metadata) akeys = [k.lower() for k in ava.keys()] res = {"less": [], "more": []} for key, attr in rest.items(): if key not in ava: if key not in akeys: res["less"].append(key)
def response(self, binding, http_args): if binding == BINDING_HTTP_ARTIFACT: resp = Redirect() else: resp = Response(http_args["data"], headers=http_args["headers"]) return resp(self.environ, self.start_response)