SocketCluster / socketcluster

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

Make SC work with passport authentication #71

Closed jondubois closed 8 years ago

jondubois commented 9 years ago

See https://github.com/TopCloud/socketcluster/issues/53

MegaGM commented 9 years ago

Any news? ^_^

vnistor commented 9 years ago

Interested in this as well.

jondubois commented 9 years ago

It's next on my TODO list.

jondubois commented 9 years ago

I'm currently making some changes to authentication (making it localStorage-based instead of cookie-based, also it will be fully customizable on both the client and server) so I need to finish that before moving on to passport... Sometime this week hopefully :(

rrNuvoPoint commented 9 years ago

Look perhaps at https://github.com/sahat/satellizer and the nodeJS module. It works for me :+1:

jondubois commented 9 years ago

@rrNuvoPoint Thanks for mentioning this! Satellizer looks like a very good solution to this problem.

@MegaGM @vnistor Note that you can do Authentication either over HTTP or over WebSockets.

Assuming I understood satellizer correcrly, a typical HTTP auth flow could be:

  1. Use satellizer to open a new Facebook OAuth window and let the user sign in
  2. Let satellizer send the resulting authorization code to the server at a specific URL (HTTP request)
  3. The server can then check that auth code with Facebook
  4. If the auth code is valid, then you can generate a new JWT auth token on the server and send it as a cookie to the client by setting the 'Set-Cookie' HTTP response header (for example).
  5. Do socketCluster.connect(...)
  6. After the socket connects, you will be able to access the JWT token from socket.request.headers.cookie (WebSockets)

^ Alternatively, you could pass the JWT token as a query parameter (in the URL) if you don't want to use cookies. But note that there are some drawbacks to this approach. See related article: https://facundoolano.wordpress.com/2014/10/11/better-authentication-for-socket-io-no-query-strings/

A typical WebSocket flow could be:

  1. Call socketCluster.connect(...)
  2. Use satellizer to open a new Facebook OAuth window and let the user sign in
  3. Get the auth code back directly on the client-side (don't send directly to server via HTTP)
  4. You can then send the code to the server over WebSockets using something like socket.emit('authFacebook', facebookAuthCode)
  5. Then on the server you can do socket.on('authFacebook', handlerFunction)
  6. Inside handlerFunction, you can check the auth code with Facebook and if it's valid, you can provide the client with a new JWT token - SC provides a method to make this easy (example) socket.setAuthToken({username: 'bob123'})
  7. Any time after this (usually inside middleware functions), you can check if the client has a token by calling socket.getAuthToken()
  8. If your token has a short expiry, remember to send the client a fresh one from time to time while they are still connected (renew the token). You can call socket.setAuthToken(...) as often as you like - Each time it will send the client a fresh token and reset the expiry

The second flow (WebSocket based) is currently the easiest way to do OAuth since SC manages the JWT tokens for you (you don't need to know anything about JWT to use it). If you choose the HTTP approach, you have to generate, sign, parse and validate the JWT token yourself which is more work.

I will try to make it easier to generate the JWT token as part of the HTTP flow too so that should make the first flow easier.

Then once that's done I will think about how to integrate with PassportJS.

jondubois commented 9 years ago

Since SC v2.2.35, you can access the default AuthEngine, from worker.auth inside your workerController. This allows you to sign (create) tokens and also verify tokens provided by clients: https://github.com/SocketCluster/socketcluster/blob/master/lib/auth.js - This may be useful if you want to do custom authentication over HTTP but don't want to write your own token signing/verification engine.

jondubois commented 8 years ago

I think satellizer seems like the best solution since SC is designed to work with JWT tokens.