socketcluster icon indicating copy to clipboard operation
socketcluster copied to clipboard

JWT auth using token from another server?

Open davidhoare opened this issue 7 years ago • 8 comments

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!

davidhoare avatar Oct 30 '18 20:10 davidhoare

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?

makarov-roman avatar Jun 13 '19 16:06 makarov-roman

@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:

  • Match the secret on the SC server to the oauth server
  • Operate with 2 jwt. Store the oauth raw token inside the SC token with setAuthToken and getAuthToken
  • Extend SC to be able to use the raw oauth token, and have a custom jwt.verify

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

chorsnell avatar Jun 18 '19 10:06 chorsnell

@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).

makarov-roman avatar Jun 18 '19 10:06 makarov-roman

@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?

chorsnell avatar Jun 18 '19 10:06 chorsnell

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

makarov-roman avatar Jun 18 '19 13:06 makarov-roman

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!

davidhoare avatar Jun 19 '19 02:06 davidhoare

@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.

jondubois avatar Jun 19 '19 06:06 jondubois

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
});

vgw-rhysc avatar Oct 11 '19 02:10 vgw-rhysc