Beispiel #1
0
    def do_auth(self, areq, redirect_uri, cinfo, request, cookie, **kwargs):
        """

        :param areq:
        :param redirect_uri:
        :param cinfo:
        :param request:
        :param cookie:
        :param authn:
        :param kwargs:
        :return:
        """
        acrs = self._acr_claims(areq)
        if acrs:
            # If acr claims are present the picked acr value MUST match
            # one of the given
            tup = (None, None)
            for acr in acrs:
                res = self.authn_broker.pick(acr, "exact")
                logger.debug("Picked AuthN broker for ACR %s: %s" % (
                    str(acr), str(res)))
                if res:  # Return the best guess by pick.
                    tup = res[0]
                    break
            authn, authn_class_ref = tup
        else:
            authn, authn_class_ref = self.pick_auth(areq)
            if not authn:
                authn, authn_class_ref = self.pick_auth(areq, "better")
                if not authn:
                    authn, authn_class_ref = self.pick_auth(areq, "any")

        if authn is None:
            return redirect_authz_error("access_denied", redirect_uri,
                                        return_type=areq["response_type"])

        try:
            try:
                _auth_info = kwargs["authn"]
            except KeyError:
                _auth_info = ""

            if "upm_answer" in areq and areq["upm_answer"] == "true":
                _max_age = 0
            else:
                _max_age = max_age(areq)

            identity, _ts = authn.authenticated_as(
                cookie, authorization=_auth_info, max_age=_max_age)
        except (NoSuchAuthentication, TamperAllert):
            identity = None
            _ts = 0
        except ToOld:
            logger.info("Too old authentication")
            identity = None
            _ts = 0
        else:
            logger.info("No active authentication")

        # gather information to be used by the authentication method
        authn_args = {"authn_class_ref": authn_class_ref}
        # Can't be something like JSON because it can't contain '"'
        if isinstance(request, Message):
            authn_args["query"] = request.to_urlencoded()
        elif isinstance(request, dict):
            authn_args["query"] = Message(**request).to_urlencoded()
        else:
            authn_args["query"] = request

        if "req_user" in kwargs:
            authn_args["as_user"] = kwargs["req_user"],

        for attr in ["policy_uri", "logo_uri", "tos_uri"]:
            try:
                authn_args[attr] = cinfo[attr]
            except KeyError:
                pass

        for attr in ["ui_locales", "acr_values"]:
            try:
                authn_args[attr] = areq[attr]
            except KeyError:
                pass

        # To authenticate or Not
        if identity is None:  # No!
            if "prompt" in areq and "none" in areq["prompt"]:
                # Need to authenticate but not allowed
                return redirect_authz_error(
                    "login_required", redirect_uri,
                    return_type=areq["response_type"])
            else:
                return authn(**authn_args)
        else:
            if re_authenticate(areq, authn):
                # demand re-authentication
                return authn(**authn_args)
            else:
                # I get back a dictionary
                user = identity["uid"]
                if "req_user" in kwargs:
                    sids_for_sub = self.sdb.get_sids_by_sub(kwargs["req_user"])
                    if sids_for_sub and user != \
                            self.sdb.get_authentication_event(
                                sids_for_sub[-1]).uid:
                        logger.debug("Wanted to be someone else!")
                        if "prompt" in areq and "none" in areq["prompt"]:
                            # Need to authenticate but not allowed
                            return redirect_authz_error("login_required",
                                                        redirect_uri)
                        else:
                            return authn(**authn_args)

        authn_event = AuthnEvent(identity["uid"], identity.get('salt', ''),
                                 authn_info=authn_class_ref,
                                 time_stamp=_ts)

        return {"authn_event": authn_event, "identity": identity, "user": user}
Beispiel #2
0
    def do_auth(self, areq, redirect_uri, cinfo, request, cookie, **kwargs):
        """

        :param areq:
        :param redirect_uri:
        :param cinfo:
        :param request:
        :param cookie:
        :param authn:
        :param kwargs:
        :return:
        """
        acrs = self._acr_claims(areq)
        if acrs:
            # If acr claims are present the picked acr value MUST match
            # one of the given
            tup = (None, None)
            for acr in acrs:
                res = self.authn_broker.pick(acr, "exact")
                logger.debug("Picked AuthN broker for ACR %s: %s" % (
                    str(acr), str(res)))
                if res:  # Return the best guess by pick.
                    tup = res[0]
                    break
            authn, authn_class_ref = tup
        else:
            authn, authn_class_ref = self.pick_auth(areq)
            if not authn:
                authn, authn_class_ref = self.pick_auth(areq, "better")
                if not authn:
                    authn, authn_class_ref = self.pick_auth(areq, "any")

        if authn is None:
            return redirect_authz_error("access_denied", redirect_uri,
                                        return_type=areq["response_type"])

        try:
            try:
                _auth_info = kwargs["authn"]
            except KeyError:
                _auth_info = ""

            if "upm_answer" in areq and areq["upm_answer"] == "true":
                _max_age = 0
            else:
                _max_age = max_age(areq)

            identity, _ts = authn.authenticated_as(
                cookie, authorization=_auth_info, max_age=_max_age)
        except (NoSuchAuthentication, TamperAllert):
            identity = None
            _ts = 0
        except ToOld:
            logger.info("Too old authentication")
            identity = None
            _ts = 0
        else:
            logger.info("No active authentication")

        # gather information to be used by the authentication method
        authn_args = {"authn_class_ref": authn_class_ref}
        # Can't be something like JSON because it can't contain '"'
        if isinstance(request, Message):
            authn_args["query"] = request.to_urlencoded()
        elif isinstance(request, dict):
            authn_args["query"] = Message(**request).to_urlencoded()
        else:
            authn_args["query"] = request

        if "req_user" in kwargs:
            authn_args["as_user"] = kwargs["req_user"],

        for attr in ["policy_uri", "logo_uri", "tos_uri"]:
            try:
                authn_args[attr] = cinfo[attr]
            except KeyError:
                pass

        for attr in ["ui_locales", "acr_values"]:
            try:
                authn_args[attr] = areq[attr]
            except KeyError:
                pass

        # To authenticate or Not
        if identity is None:  # No!
            if "prompt" in areq and "none" in areq["prompt"]:
                # Need to authenticate but not allowed
                return redirect_authz_error(
                    "login_required", redirect_uri,
                    return_type=areq["response_type"])
            else:
                return authn(**authn_args)
        else:
            if re_authenticate(areq, authn):
                # demand re-authentication
                return authn(**authn_args)
            else:
                # I get back a dictionary
                user = identity["uid"]
                if "req_user" in kwargs:
                    sids_for_sub = self.sdb.get_sids_by_sub(kwargs["req_user"])
                    if sids_for_sub and user != \
                            self.sdb.get_authentication_event(
                                sids_for_sub[-1]).uid:
                        logger.debug("Wanted to be someone else!")
                        if "prompt" in areq and "none" in areq["prompt"]:
                            # Need to authenticate but not allowed
                            return redirect_authz_error("login_required",
                                                        redirect_uri)
                        else:
                            return authn(**authn_args)

        authn_event = AuthnEvent(identity["uid"], identity.get('salt', ''),
                                 authn_info=authn_class_ref,
                                 time_stamp=_ts)

        return {"authn_event": authn_event, "identity": identity, "user": user}
Beispiel #3
0
    def auth_init(self, request, request_class=AuthorizationRequest):
        """

        :param request: The AuthorizationRequest
        :return:
        """
        logger.debug("Request: '%s'" % sanitize(request))
        # Same serialization used for GET and POST

        try:
            areq = self.server.parse_authorization_request(
                request=request_class, query=request)
        except (MissingRequiredValue, MissingRequiredAttribute,
                AuthzError) as err:
            logger.debug("%s" % err)
            areq = request_class()
            areq.lax = True
            if isinstance(request, dict):
                areq.from_dict(request)
            else:
                areq.deserialize(request, "urlencoded")
            try:
                redirect_uri = self.get_redirect_uri(areq)
            except (RedirectURIError, ParameterError, UnknownClient) as err:
                return error_response("invalid_request", "%s" % err)
            try:
                _rtype = areq["response_type"]
            except KeyError:
                _rtype = ["code"]
            try:
                _state = areq["state"]
            except KeyError:
                _state = ''

            return redirect_authz_error("invalid_request", redirect_uri,
                                        "%s" % err, _state, _rtype)
        except KeyError:
            areq = request_class().deserialize(request, "urlencoded")
            # verify the redirect_uri
            try:
                self.get_redirect_uri(areq)
            except (RedirectURIError, ParameterError) as err:
                return error_response("invalid_request", "%s" % err)
        except Exception as err:
            message = traceback.format_exception(*sys.exc_info())
            logger.error(message)
            logger.debug("Bad request: %s (%s)" % (err, err.__class__.__name__))
            err = ErrorResponse(error='invalid_request',
                                error_description=str(err))
            return BadRequest(err.to_json(), content='application/json')

        if not areq:
            logger.debug("No AuthzRequest")
            return error_response("invalid_request", "Can not parse AuthzRequest")

        areq = self.filter_request(areq)

        if self.events:
            self.events.store('Protocol request', areq)

        try:
            _cinfo = self.cdb[areq['client_id']]
        except KeyError:
            logger.error(
                'Client ID ({}) not in client database'.format(
                    areq['client_id']))
            return error_response('unauthorized_client', 'unknown client')
        else:
            try:
                _registered = [set(rt.split(' ')) for rt in
                               _cinfo['response_types']]
            except KeyError:
                # If no response_type is registered by the client then we'll
                # code which it the default according to the OIDC spec.
                _registered = [{'code'}]

            _wanted = set(areq["response_type"])
            if _wanted not in _registered:
                return error_response("invalid_request", "Trying to use unregistered response_typ")

        logger.debug("AuthzRequest: %s" % (sanitize(areq.to_dict()),))
        try:
            redirect_uri = self.get_redirect_uri(areq)
        except (RedirectURIError, ParameterError, UnknownClient) as err:
            return error_response("invalid_request", "{}:{}".format(err.__class__.__name__, err))

        try:
            keyjar = self.keyjar
        except AttributeError:
            keyjar = ""

        try:
            # verify that the request message is correct
            areq.verify(keyjar=keyjar, opponent_id=areq["client_id"])
        except (MissingRequiredAttribute, ValueError,
                MissingRequiredValue) as err:
            return redirect_authz_error("invalid_request", redirect_uri,
                                        "%s" % err)

        return {"areq": areq, "redirect_uri": redirect_uri}
Beispiel #4
0
    def auth_init(self, request, request_class=AuthorizationRequest):
        """

        :param request: The AuthorizationRequest
        :return:
        """
        logger.debug("Request: '%s'" % sanitize(request))
        # Same serialization used for GET and POST

        try:
            areq = self.server.parse_authorization_request(
                request=request_class, query=request)
        except (MissingRequiredValue, MissingRequiredAttribute,
                AuthzError) as err:
            logger.debug("%s" % err)
            areq = request_class()
            areq.lax = True
            if isinstance(request, dict):
                areq.from_dict(request)
            else:
                areq.deserialize(request, "urlencoded")
            try:
                redirect_uri = self.get_redirect_uri(areq)
            except (RedirectURIError, ParameterError, UnknownClient) as err:
                return error_response("invalid_request", "%s" % err)
            try:
                _rtype = areq["response_type"]
            except KeyError:
                _rtype = ["code"]
            try:
                _state = areq["state"]
            except KeyError:
                _state = ''

            return redirect_authz_error("invalid_request", redirect_uri,
                                        "%s" % err, _state, _rtype)
        except KeyError:
            areq = request_class().deserialize(request, "urlencoded")
            # verify the redirect_uri
            try:
                self.get_redirect_uri(areq)
            except (RedirectURIError, ParameterError) as err:
                return error_response("invalid_request", "%s" % err)
        except Exception as err:
            message = traceback.format_exception(*sys.exc_info())
            logger.error(message)
            logger.debug("Bad request: %s (%s)" % (err, err.__class__.__name__))
            err = ErrorResponse(error='invalid_request',
                                error_description=str(err))
            return BadRequest(err.to_json(), content='application/json')

        if not areq:
            logger.debug("No AuthzRequest")
            return error_response("invalid_request", "Can not parse AuthzRequest")

        areq = self.filter_request(areq)

        if self.events:
            self.events.store('Protocol request', areq)

        try:
            _cinfo = self.cdb[areq['client_id']]
        except KeyError:
            logger.error(
                'Client ID ({}) not in client database'.format(
                    areq['client_id']))
            return error_response('unauthorized_client', 'unknown client')
        else:
            try:
                _registered = [set(rt.split(' ')) for rt in
                               _cinfo['response_types']]
            except KeyError:
                # If no response_type is registered by the client then we'll
                # code which it the default according to the OIDC spec.
                _registered = [{'code'}]

            _wanted = set(areq["response_type"])
            if _wanted not in _registered:
                return error_response("invalid_request", "Trying to use unregistered response_typ")

        logger.debug("AuthzRequest: %s" % (sanitize(areq.to_dict()),))
        try:
            redirect_uri = self.get_redirect_uri(areq)
        except (RedirectURIError, ParameterError, UnknownClient) as err:
            return error_response("invalid_request", "{}:{}".format(err.__class__.__name__, err))

        try:
            keyjar = self.keyjar
        except AttributeError:
            keyjar = ""

        try:
            # verify that the request message is correct
            areq.verify(keyjar=keyjar, opponent_id=areq["client_id"])
        except (MissingRequiredAttribute, ValueError,
                MissingRequiredValue) as err:
            return redirect_authz_error("invalid_request", redirect_uri,
                                        "%s" % err)

        return {"areq": areq, "redirect_uri": redirect_uri}