Esempio n. 1
0
def issue_aft_token():
    """
    Issues a new antiforgery token to include in a page request.
    If it doesn't exist in the request, sets a cookie in the response.
    @param request
    @returns {string} the newly defined
    """
    # check if the session is defined inside the request
    if not request.session:
        raise Error("missing session inside the request object; use the AntiforgeryValidate after the membership provider")
    encryption_key = request.session.guid

    cookie_token = request.cookies.get(cookie_name)
    new_token_defined = False
    if not cookie_token:
        #define a new token
        cookie_token = uuid.uuid1()
        new_token_defined = True
    else:
        can_decrypt, value = AesEncryptor.try_decrypt(cookie_token, encryption_key)
        if not can_decrypt:
            cookie_token = uuid.uuid1()
            new_token_defined = True
        else:
            # use the same value of before
            cookie_token = value

    if new_token_defined:
        cookie_token = str(cookie_token)
        encrypted_token = AesEncryptor.encrypt(cookie_token, str(encryption_key))
        # the cookie will be set in response object inside global_handlers function
        request.set_aft_cookie = encrypted_token

    # return the token encrypted with AES; many calls always return a different value
    return AesEncryptor.encrypt(cookie_token, encryption_key)
    def set_auth_cookie(response):
        set_session_cookie = hasattr(request, "set_session_cookie")
        unset_session_cookie = hasattr(request, "unset_session_cookie")
        set_aft_cookie = hasattr(request, "set_aft_cookie")

        if set_session_cookie:
            session = request.session
            session_guid = str(session.guid)
            # encrypt:
            session_token = AesEncryptor.encrypt(session_guid, ENCRYPTION_KEY)

            response.set_cookie(session_cookie,
                                value=session_token,
                                expires=session.expiration,
                                httponly=True,
                                secure=SECURE_COOKIES)
        if unset_session_cookie:
            # instruct the browser to delete the session cookie
            response.set_cookie(session_cookie, value="", expires=0)

        if set_aft_cookie:
            session = request.session
            aft = request.set_aft_cookie
            # set the cookie in the response
            response.set_cookie("aftck",
                                value=aft,
                                expires=session.expiration,
                                httponly=True,
                                secure=SECURE_COOKIES)
            # force XSS protection, otherwise it would be pointless to issue an antiforgery token
            response.headers["X-Frame-Options"] = "SAMEORIGIN"

        return response
    def authenticate_request(*args, **kwargs):
        session_key = request.cookies.get(session_cookie)
        if session_key is None:
            # initialize an anonymous session
            initialize_anonymous_session()
        else:
            # decrypt
            session_guid = AesEncryptor.decrypt(session_key, ENCRYPTION_KEY)
            # try to perform login by session key
            success, result = membership_provider.try_login_by_session_key(
                session_guid)

            if success:
                # result is a principal object
                principal = result["principal"]
                session = result["session"]

                # set information inside the request
                setattr(request, "user", principal)
                setattr(request, "session", session)
            else:
                # set a flag to unset session cookie
                request.unset_session_cookie = True
                # initialize an anonymous session
                initialize_anonymous_session()
    def set_auth_cookie(response):
        set_session_cookie = hasattr(request, "set_session_cookie")
        unset_session_cookie = hasattr(request, "unset_session_cookie")
        set_aft_cookie = hasattr(request, "set_aft_cookie")

        if set_session_cookie:
            session = request.session
            session_guid = str(session.guid)
            # encrypt:
            session_token = AesEncryptor.encrypt(session_guid, ENCRYPTION_KEY)

            response.set_cookie(session_cookie,
                                value=session_token,
                                expires=session.expiration,
                                httponly=True,
                                secure=SECURE_COOKIES)
        if unset_session_cookie:
            # instruct the browser to delete the session cookie
            response.set_cookie(session_cookie, value="", expires=0)

        if set_aft_cookie:
            session = request.session
            aft = request.set_aft_cookie
            # set the cookie in the response
            response.set_cookie("aftck",
                                value=aft,
                                expires=session.expiration,
                                httponly=True,
                                secure=SECURE_COOKIES)
            # force XSS protection, otherwise it would be pointless to issue an antiforgery token
            response.headers["X-Frame-Options"] = "SAMEORIGIN"

        return response
Esempio n. 5
0
    async def initialize_anonymous_session(self, request: Request):
        """
        Initializes an anonymous session for the given request.

        :param request: incoming request to a resource that is related to this logical area.
        """
        client_ip = self.get_client_ip(request)
        result = await self.membership.initialize_anonymous_session(
            client_ip, client_data=request.headers.get("User-Agent"))

        # set a flag to set a session cookie
        session = result.session
        session_cookie_name = self.config.session_cookie_name
        encryption_key = self.config.encryption_key
        session_cookie_value = AesEncryptor.encrypt(str(session.guid),
                                                    encryption_key)

        request.set_session_cookie = True
        request.cookies_to_set.append(
            CookieToken(session_cookie_name,
                        session_cookie_value,
                        httponly=True,
                        secure=self.secure_cookies))
        # store user and session information in the request object
        request.user = result.principal
        request.session = session
def validate_aft(request):
    """
    Validates the AFT of a given request.
    Utilizes dual token strategy (session based encrypted token, issued in both cookie and page);
    sent at each request in both cookie and request header, for ajax requests or form values.
    """
    # ignore get, options, head
    if request.method in AFT_IGNORE_METHODS:
        return

    # requires the request to have a session
    if not request.session:
        raise RuntimeError(
            "Missing session inside the request object; cannot issue an AFT without session."
        )
    # expect the request session to have a guid
    encryption_key = request.session.guid

    # get the tokens: one is always in the cookie; the second may be inside form or request header
    # request header is more important, assuming that pages implement AJAX requests, rather than form submission
    cookie_token = request.cookies.get(cookie_name)
    second_token = request.headers[
        header_name] if header_name in request.headers else None

    if second_token is None:
        # try to read from form
        second_token = request.form[
            form_name] if form_name in request.form else None

    # are the tokens present?
    if not cookie_token or not second_token:
        raise InvalidAntiforgeryTokenException()

    # decrypt the tokens; decryption will fail if the tokens were issued for another session;
    a, cookie_token = AesEncryptor.try_decrypt(cookie_token, encryption_key)
    b, second_token = AesEncryptor.try_decrypt(second_token, encryption_key)

    if not a or not b or not cookie_token or not second_token:
        raise InvalidAntiforgeryTokenException()

    # are the tokens identical?
    if cookie_token != second_token:
        raise InvalidAntiforgeryTokenException()
def issue_aft(request):
    """
    Issues a new session based antiforgery token.

    This solution implements the double token strategy: the same antiforgery token is serialized twice,
    hence producing two different encrypted strings. One is set as response cookie; one is returned to be rendered
    inside the html view.
    """
    # check if the session is defined inside the request
    if not hasattr(request, "session"):
        # missing session context; use the AntiforgeryValidate after the membership provider
        raise ValueError("missing session context")
    encryption_key = str(request.session.guid)

    cookie_token = request.cookies.get(cookie_name)
    if not cookie_token:
        #define a new token
        cookie_token = uuid.uuid1()
    else:
        can_decrypt, value = AesEncryptor.try_decrypt(cookie_token,
                                                      encryption_key)
        if not can_decrypt:
            cookie_token = uuid.uuid1()
        else:
            # use the same value of before
            cookie_token = value

    # will set a new cookie in the response object
    cookie_token = str(cookie_token)
    encrypted_token = AesEncryptor.encrypt(cookie_token, encryption_key)
    # the cookie will be set in response object inside global_handlers function
    request.cookies_to_set.append(
        CookieToken(cookie_name,
                    encrypted_token.decode("utf-8"),
                    httponly=True,
                    secure=configuration.secure_cookies))

    # return the token encrypted with AES; many calls always return a different value
    v = AesEncryptor.encrypt(cookie_token, encryption_key)
    return v.decode("utf-8")
Esempio n. 8
0
        def wrapped(*args, **kwargs):
            if re.match("^(get|options|head)$", request.method, re.IGNORECASE):
                return f(*args, **kwargs)

            # check if the session is defined inside the request
            if not request.session:
                raise Error("missing session inside the request object; use the AntiforgeryValidate after the membership provider")
            encryption_key = request.session.guid

            # get the tokens: one is always in the cookie; the second may be inside form or request header
            # request header is more important, assuming that pages implement AJAX requests, rather than form submission
            cookie_token = request.cookies.get(cookie_name)
            second_token = request.headers[header_name] if header_name in request.headers else None

            if second_token is None:
                # try to read from form
                second_token = request.form[form_name] if form_name in request.form else None

            # are the tokens present?
            if not cookie_token or not second_token:
                return handle_unauthorized()

            # decrypt the tokens; decryption will fail if the tokens were issued for another session;
            a, cookie_token = AesEncryptor.try_decrypt(cookie_token, encryption_key)
            b, second_token = AesEncryptor.try_decrypt(second_token, encryption_key)

            if not a or not b or not cookie_token or not second_token:
                return handle_unauthorized()

            # are the tokens identical?
            if cookie_token != second_token:
                return handle_unauthorized()

            # validation succeeded
            # continue normally
            return f(*args, **kwargs)
Esempio n. 9
0
    async def _authenticate_user(self, request: Request):
        """
        If the area features membership, it invokes the methods of the underlying membership provider to authenticate
        the user, supporting anonymous authentication.

        :param request: request to authenticate.
        """
        request.user = None
        encryption_key = self.config.encryption_key
        membership = self.membership
        set_anonymous_session = False

        if self.membership:
            # does the request contains the session cookie for this area?
            session_cookie_name = self.config.session_cookie_name
            session_key = request.cookies.get(session_cookie_name)
            if session_key:
                # try to load the session
                # decrypt the session key
                success, session_guid = AesEncryptor.try_decrypt(
                    session_key, encryption_key)
                if success:
                    # try to perform login by session key
                    success, result = await membership.try_login_by_session_key(
                        session_guid)
                    if success:
                        # result is a principal object
                        request.user = result.principal
                        request.session = result.session
                    else:
                        # the login by session cookie failed: the session could be expired
                        set_anonymous_session = True
                else:
                    # session key decryption failed
                    set_anonymous_session = True
            else:
                # the request does not contain a session cookie for this area
                set_anonymous_session = True

        if set_anonymous_session:
            # initialize an anonymous session
            await self.initialize_anonymous_session(request)
        return self
    def authenticate_request(*args, **kwargs):
        session_key = request.cookies.get(session_cookie)
        if session_key is None:
            # initialize an anonymous session
            initialize_anonymous_session()
        else:
            # decrypt
            session_guid = AesEncryptor.decrypt(session_key, ENCRYPTION_KEY)
            # try to perform login by session key
            success, result = membership_provider.try_login_by_session_key(session_guid)

            if success:
                # result is a principal object
                principal = result["principal"]
                session = result["session"]

                # set information inside the request
                setattr(request, "user", principal)
                setattr(request, "session", session)
            else:
                # set a flag to unset session cookie
                request.unset_session_cookie = True
                # initialize an anonymous session
                initialize_anonymous_session()