Search code examples
authenticationcookieseve

How do you handle cookie based authentication in Eve?


I'm using Eve 0.7, Eve-Sqlalchemy 0.7.1, and a TokenBasedAuth class implemented and set on my domains. It works as design for requests that are sending a token via the Authorization header.

Example that works as designed locally:

curl -sk -X GET -H "Authorization:Bearer $MY_JWT" localhost:5000/my_domain

I have a use case where a client would like to send a Cookie header with the auth token inside it. However, when I try that kind of request

curl -sk -X GET -H "Cookie: $MY_COOKIE" localhost:5000/my_domain

I get a response of

{
    "_status": "ERR",
    "_error": {
        "code": 401,
        "message": "Please provide proper credentials"
    }
}

Is there a way to handle Cookie based-authentication in Eve 0.7?

So far I've tried adding some logging statements to the on_pre_GET event hook to try and peak at what's going on, but the hook never fires. I'm assuming something might be happening internally to return a 401 since there's no auth header (I haven't looked at the source code yet so just guessing).

I've also set X_ALLOW_CREDENTIALS = True in my settings, but I don't think that's the way to go about this (if I'm wrong just let me know!).

Thanks for reading and any help you can provide!


Update

I read through eve/auth.py (https://github.com/pyeve/eve/blob/52a927fe69ff05d3098d62145efe1fbfaddb5cf9/eve/auth.py) and I believe I can override authorized (https://github.com/pyeve/eve/blob/52a927fe69ff05d3098d62145efe1fbfaddb5cf9/eve/auth.py#L258) to do what I need it. Once I verify I can update again.


Solution

  • The token auth class (https://github.com/pyeve/eve/blob/52a927fe69ff05d3098d62145efe1fbfaddb5cf9/eve/auth.py#L230) has an authorized() method that you can override.

    However, it's not a documented method for overriding, so know that doing so you could run into issues in different versions of Eve.

    The way I modified the method was to have it look for a Cookie header, and if found, try to get an auth token from it. If it finds one and check_auth returns true, call set_user_or_token and return.

    If there's no cookie header, or the token does not check_auth successfully, fall through to the parent class' authorized method to handle other cases (such as an Authorization header).

    class MyTokenAuth(TokenAuth):
        def authorized(self, allowed_roles, resource, method):
            auth = None
            if request.headers.get("Cookie"):
                auth = self.try_to_get_auth_from_cookie(request.headers.get("Cookie"))
    
            if auth and self.check_auth(auth, allowed_roles, resource, method):
                super().set_user_or_token(auth)
                return True
    
            return super().authorized(allowed_roles, resource, method)