SocketCluster / socketcluster

Highly scalable realtime pub/sub and RPC framework
https://socketcluster.io
MIT License
6.15k stars 314 forks source link

JWT auth using token from another server? #452

Open davidhoare opened 6 years ago

davidhoare commented 6 years ago

I've got a Slim server working well to register and authenticate users for our API, using JWT, allowing only 'authenticated' users to access certain api endpoints.

I'm now trying to setup a SocketCluster for various realtime messaging parts of the app, and I would like to restrict subscriptions to only authenticated users. I may be missing a part of the concept, but is it not possible to use the token-cookie set successfully by Slim to also authenticate to SocketCluster? (ideally using the built-in authentication process, and without having to call-back to the slim-api?) They're on different servers as sub-domains... Would I have to insert the same secret into the SocketCluster configuration somewhere?

Thank you!

makarov-roman commented 5 years ago

I have similar case. I have my own JWT Token (oauth) and want to use it for SC too. If there is a need to keep some SC-related data in JWT, it would be also okay to generate JWT with SC. Is there a way to achieve this without having two JWT tokens?

chorsnell commented 5 years ago

@davidhoare @makarov-roman did either of you find a nice solution for this?

I too have an external oauth that I have integrated with jsonwebtoken and jwka-rsa, which works nicely. However as you both mention, socketcluster has its own jwt auth baked in that interferes with this.

I need to use the original jwt to pass through to make api requests made from the socketcluster server on behalf of the connected client.

Options:

None of these feel particularly elegant / the right course of action. @jondubois is there any easy solution we are missing?

makarov-roman commented 5 years ago

@poppahorse Currently we are using two JWT tokens. It would be more convenient to pass JWT to SC or generate token via SC without WS connection(in the rest login endpoint).

chorsnell commented 5 years ago

@makarov-roman do you actually need the original token for anything once its on the server? or only as a mean to verify the connection?

makarov-roman commented 5 years ago

@poppahorse yes, we store userID and some data in it. It's required for both REST API and SC.

davidhoare commented 5 years ago

ultimately I found another work-around... I'm storing the SLIM-generated token in a cookie, and then on my other subdomain that needed to also check for validation, I'm using the Firebase\JWT library to do a second validation of the stored token, which then allows that page to proceed or stop. sorry!

jondubois commented 5 years ago

@davidhoare Glad you found a work around. One possible solution is to use a custom authEngine. The default can be replaced on both the client and server side.

On the server side you need to pass an authEngine property when instantiating the main SocketCluster instance - It need to contain an instance of your custom server-side auth engine. It's just an object which implements a verifyToken and signToken method. The default server side authEngine is here so you could just copy paste it and modify it for your use case and handle whatever token you like (just make sure that the returned values match the format of the default authEngine): https://github.com/SocketCluster/sc-auth/blob/master/index.js

For client side, you can also pass a custom authEngine see: https://socketcluster.io/#!/docs/api-socketcluster-client - It serves a different purpose though and so has a different interface. The default client auth engine is here: https://github.com/SocketCluster/socketcluster-client/blob/90c78f94cb3e94f714fe00d25d9326358d227d83/lib/auth.js#L22-L56 so you can also copy-past and modify.

vgw-rhysc commented 5 years ago

Note there is some guidance here from the library maintainers on how you could use jwt.verify in your custom auth engine https://github.com/auth0/node-jsonwebtoken

// Verify using getKey callback
// Example uses https://github.com/auth0/node-jwks-rsa as a way to fetch the keys.
var jwksClient = require('jwks-rsa');
var client = jwksClient({
  jwksUri: 'https://sandrino.auth0.com/.well-known/jwks.json'
});
function getKey(header, callback){
  client.getSigningKey(header.kid, function(err, key) {
    var signingKey = key.publicKey || key.rsaPublicKey;
    callback(null, signingKey);
  });
}

jwt.verify(token, getKey, options, function(err, decoded) {
  console.log(decoded.foo) // bar
});