示例#1
0
    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
示例#2
0
    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
示例#3
0
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)
示例#4
0
    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!")
示例#5
0
    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
示例#6
0
    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])
示例#7
0
    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)
示例#8
0
    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
示例#9
0
 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])
示例#10
0
    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