feathers icon indicating copy to clipboard operation
feathers copied to clipboard

Is socket connection coupled with JWT token expiry?

Open bwgjoseph opened this issue 5 years ago • 9 comments

Hi,

Would like to know if the socket connection is coupled with JWT token expiry? I'm trying to verify this information but wasn't able to find a definite answer yet.

So I have this scenario where

( expiresIn is set to 60s)

  • client login via websocket, and get back token1
  • client listen to real-time event via websocket
  • client perform a login via REST, and get back token2
  • client did a POST to service-x using token2 (REST), and able to listen to the websocket event (before the 60s expiry is up)
  • client did another POST to service-x using token2 (REST), and now does not receive any websocket event (after the 60s expiry)

In the debug logs, I could only see No connections to publish to after the 2nd POST is done. The actual creation is still completed since token2 is still valid

So does that mean that once a socket JWT issued token has expired, it will cause the connection to leave all channels but the connection between client and server is still alive? Because as far as I can tell, there is no disconnect message in client nor server.

Thanks

bwgjoseph avatar Jan 18 '21 18:01 bwgjoseph

Yes, connections will trigger a disconnect event and removed from all channels automatically upon token expiry (see https://github.com/feathersjs/feathers/blob/dove/packages/authentication/src/jwt.ts#L46) and no longer receive real-time updates. It would be the client's responsibility to handle their token expiry and reauthentication.

daffl avatar Jan 18 '21 18:01 daffl

But this only trigger a disconnect event but don't actually disconnect the actual connection between client and server right?

bwgjoseph avatar Jan 18 '21 18:01 bwgjoseph

Correct. If you intentionally have shorter token expiries while the client doesn't do anything (when the token is expired and they try to make a request it'll throw an error to log in again anyway) it makes sense for the client to keep track of that and prompt the user to log in again (or request a new token otherwise) once it is expired.

As you can see in the comment in the code linked I've been going back and forth between it being a disconnect or a logout event.

daffl avatar Jan 19 '21 02:01 daffl

Alright, thank you for the clarification

bwgjoseph avatar Jan 20 '21 16:01 bwgjoseph

This was a good question. I've been thinking about ways for the server to let the client know that their connection has expired but I can't think of a good one other than just disconnecting which might not be what we want so handling it on the client side probably makes the most sense for now and potentially could be built into the client.

daffl avatar Jan 20 '21 17:01 daffl

I think disconnecting make sense, disconnect event is to be handled on server end to leave channels and all

Just thinking out loud, would it be possible to emit a custom event - token expiring to user service so client can listen to such event and react accordingly. Although, all these can be made possible in client but just decoding the token and grab the expiry and use setTimeout or something to reauthenticate couple of mins before expiry. It just make it slightly easier for client to react, since it doesn't need to write the boilerplate (decode, settimeout...)

bwgjoseph avatar Jan 20 '21 18:01 bwgjoseph

In terms of security is better to disconnect the user. To reconnect need to handle the event disconnect of socket.io, then connect again and authenticate.

Maybe can send an event previous to disconnection to know the JWT was expired, and then try to refresh. That, before reconnection.

matiaslopezd avatar Jun 17 '21 16:06 matiaslopezd

@daffl So if a token expires, client will have to clear the storage and sign out user. Feathers client does not handle that is what you're saying ?? . Btw, just started learning feathers and I really like it. I come from django/django-rest-framework background , so feathers does similar in some way. Also, I use React with TypeScript, is there any way to defind a return type when fetching data

Something like this ???
 const resp = await feathersClient.service('user').get<User>() 

kylenguyen1014 avatar Jul 27 '21 17:07 kylenguyen1014

Client does not need to clear storage or sign out. If you are using feathers-client then you can try to call reAuthenticate method or simply call authenticate again before your session ends. This, however, would means that you need to keep track of the expiry in the client side. Alternatively, you could just prompt user to sign in again.

bwgjoseph avatar Jul 28 '21 12:07 bwgjoseph

I just realised that while addressing https://github.com/feathersjs/feathers/issues/2754 in the PR at https://github.com/feathersjs/feathers/pull/2896 I think this also applies to this issue. If a token expires the client socket will now be disconnected, try to reauthenticate again and then get an error that the token is expires. I believe we can close this now.

daffl avatar Nov 28 '22 05:11 daffl