Cookie-based authentication

358 views
Skip to first unread message

James Coglan

unread,
Jun 14, 2011, 3:52:02 PM6/14/11
to faye-...@googlegroups.com
Hi everyone,

I'm opening up a question I was asked on GitHub because I'd like feedback to make sure I'm not doing anything wrong. asp24 asked the following:

<quote>
Here is the second problem. At faye server (we are using js one) i need to auth users. I added a little bit of monkey-patching for request filtering.

    (function (faye_node_adapter){
        var native_check = faye_node_adapter.check;

        faye_node_adapter.check = function(request) {
            if (request.headers && 'x-forwarded-for' in request.headers) {
                // BAD and DIRTY hack
                request.headers['x-forwarded-proto'] = 'https';
            }
            return SessionStorage.checkRequest(request, function(err){
                return err ? false : native_check.call(faye_node_adapter, request);
            })
        }
    })(faye_node_adapter);

We are using session id from http-only cookie for request filtering.
</quote>

So the question is really: how can we do cookie-based authentication in a clean way without patching Faye when we're using http-only cookies (which are invisible to JavaScript). Faye extensions do not give you access to the HTTP request, so how can we do it?

I've built a demo of a scheme I think might work for this: https://github.com/jcoglan/faye-cookie-auth. The scheme works as follows:

The client adds an extension to add tokens to /meta/subscribe messages [1]. It gets these tokens by making an Ajax call to an endpoint that will return a token for logged in users [2]. I've used a constant but really you should generate a unique unguessable token for the user.

On the server-side, an incoming extension checks for the presence of this token. If it is missing the subscription is denied [3]. Again, in real life do not use a constant, validate that the token is real and do whatever you need to check which user it belongs to.

I know this works, but I want to know if I've introduced a security hole. If we're doing cookie-based auth as with the hack above, malicious script on the page will still be able to subscribe because it will send the same cookies as our code. By similar logic malicious code injected into a site can read any data a logged-in user has access to. So, I don't think I'm introducing capabilities the malicious script would not otherwise have.

Thoughts?

James Coglan

unread,
Jun 14, 2011, 4:08:14 PM6/14/11
to Faye users
On Jun 14, 8:52 pm, James Coglan <jcog...@gmail.com> wrote:
> I know this works, but I want to know if I've introduced a security hole. If
> we're doing cookie-based auth as with the hack above, malicious script on
> the page will still be able to subscribe because it will send the same
> cookies as our code. By similar logic malicious code injected into a site
> can read any data a logged-in user has access to. So, I don't think I'm
> introducing capabilities the malicious script would not otherwise have.

Further to this: http-only cookies are valuable because if malicious
script steals a session cookie, it can post it to another server than
can carry on stealing user data after the browser window has closed.

This scheme, on the other hand, exposes tokens with very limited
utility, i.e. subscribing to the site's message bus, without leaking
the session cookies that would give an attacker access to the user's
entire identity. Obviously, since we're trying to protect the message
bus I assume there is sensitive data going over it, so leaking a token
that provides access to it is undesirable.

Could this be solved by making the token very short-lived? Or is there
a better way? Should I bite the bullet and add filtering at the
network transport level? I'm not sure how this would affect WebSocket,
and I've no idea how many people need this functionality.

Matthijs Langenberg

unread,
Jun 15, 2011, 3:20:43 AM6/15/11
to faye-...@googlegroups.com
Thanks for bringing this up. There are multiple ways to achieve this, I think we need to pick one as a convention and support it from within Faye.
The real challenge is in generating a short-lived token. There are at least two approaches to this.

  1. Client retrieves a unique user-specific generated token from an endpoint. Faye server uses a variant of this endpoint to verify to token and additionally retrieves some user data.
  2. Client retrieves a signed token from an endpoint. Faye server uses a shared secret to verify the signature of the token.
We have opted for the second approach. Because this also allows us to connect to the same Faye server from different websites. As long as an application knows how to generated a valid signed token (using the shared secret), it can connect users to the Faye server.

Please be aware that checking a token only on subscription is not enough. Because there is no requirement to be subscribed to a channel when publishing to it. For instance, only authorized clients are allowed to publish to the '/chats' channel. 

If you are interested I can publish the code that we use for handling signed tokens (faye-client extensions, faye-server extensions and signed-token generation code).


Bests,

Matthijs 

dazoakley

unread,
Mar 7, 2012, 9:55:58 AM3/7/12
to faye-...@googlegroups.com
Hi Matthijs,

Sorry for re-opening an old conversation...

I'm just in the process of trying to put up a Faye server and I need to add authentication as well.  Are you still using Faye in this way and ok to share some examples of how you implemented the authentication?

Anyone else got any ideas/examples/suggestions on this problem?

Thanks in advance,

Daz


On Wednesday, June 15, 2011 8:20:43 AM UTC+1, Matthijs Langenberg wrote:
Thanks for bringing this up. There are multiple ways to achieve this, I think we need to pick one as a convention and support it from within Faye.
The real challenge is in generating a short-lived token. There are at least two approaches to this.

  1. Client retrieves a unique user-specific generated token from an endpoint. Faye server uses a variant of this endpoint to verify to token and additionally retrieves some user data.
  2. Client retrieves a signed token from an endpoint. Faye server uses a shared secret to verify the signature of the token.
We have opted for the second approach. Because this also allows us to connect to the same Faye server from different websites. As long as an application knows how to generated a valid signed token (using the shared secret), it can connect users to the Faye server.

Please be aware that checking a token only on subscription is not enough. Because there is no requirement to be subscribed to a channel when publishing to it. For instance, only authorized clients are allowed to publish to the '/chats' channel. 

If you are interested I can publish the code that we use for handling signed tokens (faye-client extensions, faye-server extensions and signed-token generation code).


Bests,

Matthijs 

On Tue, Jun 14, 2011 at 10:08 PM, James Coglan wrote:
On Jun 14, 8:52 pm, James Coglan wrote:
On Tue, Jun 14, 2011 at 10:08 PM, James Coglan wrote:
Reply all
Reply to author
Forward
0 new messages