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)" % sanitize(request)) if isinstance(request, six.string_types): _dict = compact(parse_qs(request)) elif isinstance(request, dict): _dict = request else: raise ValueError("Wrong type of input") logger.debug("dict: %s" % sanitize(_dict)) # verify username and password try: self._verify(_dict["password"], _dict["login"]) # dict origin except TypeError: try: self._verify(_dict["password"][0], _dict["login"][0]) except (AssertionError, KeyError) as err: logger.debug("Password verification failed: {}".format(err)) resp = Unauthorized("Unknown user or wrong password") return resp, False else: try: _qp = _dict["query"] except KeyError: _qp = self.get_multi_auth_cookie(kwargs['cookie']) except (AssertionError, KeyError) as err: logger.debug("Password verification failed: {}".format(err)) resp = Unauthorized("Unknown user or wrong password") return resp, False else: try: _qp = _dict["query"] except KeyError: _qp = self.get_multi_auth_cookie(kwargs['cookie']) logger.debug("Password verification succeeded.") # if "cookie" not in kwargs or self.srv.cookie_name not in kwargs["cookie"]: headers = [self.create_cookie(_dict["login"], "upm")] try: return_to = self.generate_return_url(kwargs["return_to"], _qp) except KeyError: try: return_to = self.generate_return_url(self.return_to, _qp, kwargs["path"]) except KeyError: return_to = self.generate_return_url(self.return_to, _qp) return SeeOther(return_to, headers=headers), True
def response(self, binding, http_args, query): cookie = self.create_cookie( '{"' + self.CONST_QUERY + '": "' + base64.b64encode(query.encode("ascii")).decode("ascii") + '" , "' + self.CONST_HASIDP + '": "True" }', self.CONST_SAML_COOKIE, self.CONST_SAML_COOKIE) if binding == BINDING_HTTP_ARTIFACT: resp = SeeOther() elif binding == BINDING_HTTP_REDIRECT: for param, value in http_args["headers"]: if param == "Location": resp = SeeOther(str(value), headers=[cookie]) break else: raise ServiceErrorException("Parameter error") else: http_args["headers"].append(cookie) resp = Response(http_args["data"], headers=http_args["headers"]) return resp
def redirect_authz_error(error, redirect_uri, descr=None, state="", return_type=None): err = AuthorizationErrorResponse(error=error) if descr: err["error_description"] = descr if state: err["state"] = state if return_type is None or return_type == ["code"]: location = err.request(redirect_uri) else: location = err.request(redirect_uri, True) return SeeOther(location)
def verify(self, request, cookie, **kwargs): """ Verifies if the authentication was successful. :rtype : Response :param request: Contains the request parameters. :param cookie: Cookies sent with the request. :param kwargs: Any other parameters. :return: If the authentication was successful: a redirect to the return_to url. Otherwise a unauthorized response. :raise: ValueError """ 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") try: cas_cookie, _ts, _typ = self.getCookieValue( cookie, self.CONST_CAS_COOKIE) data = json.loads(cas_cookie) nonce = base64.b64decode(data[self.CONST_NONCE]) if nonce != _dict[self.CONST_NONCE][0]: logger.warning( 'Someone tried to login without a correct nonce!') return Unauthorized("You are not authorized!") acr = None try: acr = _dict["acr_values"][0] except KeyError: pass uid = self.handle_callback(_dict[self.CONST_TICKET], self.get_service_url(nonce, acr)) if uid is None or uid == "": logger.info('Someone tried to login, but was denied by CAS!') return Unauthorized("You are not authorized!") cookie = self.create_cookie(uid, "casm") return_to = self.generate_return_url(self.return_to, uid) if '?' in return_to: return_to += "&" else: return_to += "?" return_to += base64.b64decode(data[self.CONST_QUERY]) return SeeOther(return_to, headers=[cookie]) except Exception: # FIXME: This should catch specific exception thrown from methods in the block logger.fatal('Metod verify in user_cas.py had a fatal exception.', exc_info=True) return Unauthorized("You are not authorized!")
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") logger.debug("dict: %s" % _dict) logger.debug("passwd: %s" % self.passwd) # verify username and password try: assert _dict['login_parameter'][0] == 'logged_in' except (AssertionError, KeyError): resp = Unauthorized( "You are not authorized. Javascript not executed") return resp, False else: cookie = self.create_cookie("diana", "upm") try: _qp = _dict["query"][0] except KeyError: _qp = self.get_multi_auth_cookie(kwargs['cookie']) try: return_to = self.generate_return_url(kwargs["return_to"], _qp) except KeyError: return_to = self.generate_return_url(self.return_to, _qp) resp = SeeOther(return_to, headers=[cookie]) return resp, True
def create_redirect(self, query): """ Performs the redirect to the CAS server. :rtype : Response :param query: All query parameters to be added to the return_to URL after successful authentication. :return: A redirect response to the CAS server. """ try: req = parse_qs(query) acr = req['acr_values'][0] except KeyError: acr = None nonce = uuid.uuid4().get_urn() service_url = urlencode( {self.CONST_SERVICE: self.get_service_url(nonce, acr)}) cas_url = self.cas_server + self.CONST_CASLOGIN + service_url cookie = self.create_cookie( '{"' + self.CONST_NONCE + '": "' + base64.b64encode(nonce) + '", "' + self.CONST_QUERY + '": "' + base64.b64encode(query) + '"}', self.CONST_CAS_COOKIE, self.CONST_CAS_COOKIE) return SeeOther(cas_url, headers=[cookie])
def authz_part2(self, user, areq, sid, **kwargs): """ After the authentication this is where you should end up :param user: :param areq: The Authorization Request :param sid: Session key :param kwargs: possible other parameters :return: A redirect to the redirect_uri of the client """ result = self._complete_authz(user, areq, sid, **kwargs) if isinstance(result, Response): return result else: aresp, headers, redirect_uri, fragment_enc = result # Mix-Up mitigation aresp['iss'] = self.baseurl aresp['client_id'] = areq['client_id'] # Just do whatever is the default location = aresp.request(redirect_uri, fragment_enc) logger.debug("Redirected to: '%s' (%s)" % (location, type(location))) return SeeOther(str(location), headers=headers)
def verify(self, request, cookie, path, requrl, end_point_index=None, **kwargs): """ Verifies if the authentication was successful. :rtype : Response :param request: Contains the request parameters. :param cookie: Cookies sent with the request. :param kwargs: Any other parameters. :return: If the authentication was successful: a redirect to the return_to url. Otherwise a unauthorized response. :raise: ValueError """ if isinstance(request, six.string_types): request = parse_qs(request) elif isinstance(request, dict): pass else: raise ValueError("Wrong type of input") acs = self.sp.config.getattr("endpoints", "sp")["assertion_consumer_service"] acs_endpoints = [(ep[0].rsplit("/", 1)[1], ep[1]) for ep in acs] binding = None path = path[1:] for endp in acs_endpoints: if path == endp[0]: binding = endp[1] break saml_cookie, _ts, _typ = self.getCookieValue(cookie, self.CONST_SAML_COOKIE) data = json.loads(saml_cookie) rp_query_cookie = self.get_multi_auth_cookie(cookie) query = rp_query_cookie if not query: query = base64.b64decode(data[self.CONST_QUERY]).decode("ascii") if data[self.CONST_HASIDP] == 'False': (done, response) = self._pick_idp(request, end_point_index) if done == 0: entity_id = response # Do the AuthnRequest resp = self._redirect_to_auth(self.sp, entity_id, query, end_point_index) return resp, False return response, False if not request: logger.info("Missing Response") return Unauthorized("You are not authorized!"), False try: response = self.sp.parse_authn_request_response( request["SAMLResponse"][0], binding, self.cache_outstanding_queries) except UnknownPrincipal as excp: logger.error("UnknownPrincipal: %s" % (excp,)) return Unauthorized(self.not_authorized), False except UnsupportedBinding as excp: logger.error("UnsupportedBinding: %s" % (excp,)) return Unauthorized(self.not_authorized), False except VerificationError as err: logger.error("Verification error: %s" % (err,)) return Unauthorized(self.not_authorized), False except Exception as err: logger.error("Other error: %s" % (err,)) return Unauthorized(self.not_authorized), False if self.sp_conf.VALID_ATTRIBUTE_RESPONSE is not None: for k, v in six.iteritems(self.sp_conf.VALID_ATTRIBUTE_RESPONSE): if k not in response.ava: return Unauthorized(self.not_authorized), False else: allowed = False for allowed_attr_value in v: if isinstance(response.ava[k], list): for resp_value in response.ava[k]: if allowed_attr_value in resp_value: allowed = True break elif allowed_attr_value in response.ava[k]: allowed = True break if not allowed: return Unauthorized(self.not_authorized), False # logger.info("parsed OK")' uid = response.assertion.subject.name_id.text if self.userinfo == "AA": if response.entity_id is not None and self.samlcache is not None: self.samlcache["AA_ENTITYID"] = response.entity_id self.setup_userdb(uid, response.ava) return_to = create_return_url(self.return_to, uid, **{self.query_param: "true"}) if '?' in return_to: return_to += "&" else: return_to += "?" return_to += query auth_cookie = self.create_cookie(uid, "samlm") resp = SeeOther(str(return_to), headers=[auth_cookie]) return resp, True
def _wayf_redirect(self, cookie): sid_ = sid() self.cache_outstanding_queries[sid_] = self.verification_endpoint return -1, SeeOther(headers=[ ('Location', "%s?%s" % (self.sp_conf.WAYF, sid_)), cookie])
def _pick_idp(self, query, end_point_index): """ If more than one idp and if none is selected, I have to do wayf or disco """ query_dict = {} if isinstance(query, six.string_types): query_dict = dict(parse_qs(query)) else: for key, value in six.iteritems(query): if isinstance(value, list): query_dict[key] = value[0] else: query_dict[key] = value query = urlencode(query_dict) _cli = self.sp # Find all IdPs idps = self.sp.metadata.with_descriptor("idpsso") idp_entity_id = None if len(idps) == 1: # idps is a dictionary idp_entity_id = list(idps.keys())[0] if not idp_entity_id and query: try: _idp_entity_id = query_dict[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: cookie = self.create_cookie( '{"' + self.CONST_QUERY + '": "' + base64.b64encode(query) + '" , "' + self.CONST_HASIDP + '": "False" }', self.CONST_SAML_COOKIE, self.CONST_SAML_COOKIE) if self.sp_conf.WAYF: if query: try: wayf_selected = query_dict["wayf_selected"][0] except KeyError: return self._wayf_redirect(cookie) idp_entity_id = wayf_selected else: return self._wayf_redirect(cookie) elif self.sp_conf.DISCOSRV: if query: idp_entity_id = _cli.parse_discovery_service_response(query=query) if not idp_entity_id: sid_ = sid() self.cache_outstanding_queries[sid_] = self.verification_endpoint eid = _cli.config.entityid disco_end_point_index = end_point_index["disco_end_point_index"] ret = _cli.config.getattr("endpoints", "sp")[ "discovery_response"][disco_end_point_index][0] ret += "?sid=%s" % sid_ loc = _cli.create_discovery_service_request( self.sp_conf.DISCOSRV, eid, **{"return": ret}) return -1, SeeOther(loc, headers=[cookie]) elif not len(idps): raise ServiceErrorException( 'Misconfiguration for the SAML Service Provider!') else: return -1, NotImplemented("No WAYF or DS present!") return 0, idp_entity_id