feathers
                                
                                 feathers copied to clipboard
                                
                                    feathers copied to clipboard
                            
                            
                            
                        No apparent way to restore a Socket IO connection on the client once a JWT expires
Issue
Expired JWT's close the client Socket IO connection entirely.
If there is an active authenticated socket io connection and the jwt expires, the connection is closed by the server and there is no apparent way to restore the connection in the client in order to re-authenticate again without creating a whole new client.
Calling app.io.connect() attempts to connect and authenticate using the same credentials and fails. Thus preventing and further requests from propagating to the server.
I'm not sure if this behaviour is by design, but if it is then I think it may be beneficial to document how to handle the reconnecting of the client following a JWT expiration.
Related To
- Socket IO
- Socket IO Client
- Authentication
Steps to reproduce
- Create a new FeathersJS app using the CLI
- Set up authentication using the CLI using the defaults
- Set the JWT configuration expiration to something quick like 15 seconds
- Bundle and link the client
- Open your frontend application code
- Setup the client to use SocketIO
const socket = io('http://localhost:3030');
  
const socketConnection = socketio<ServiceTypes>(socket)
const socketClient = createClient(socketConnection);
- Log in using local strategy
- Wait for token to expire on the server
- Make any form of request using the client, including: app.authenticate({ ... }).
Expected behavior
After the JWT expires, the requests should still be sent to the server and handle as not authenticated.
Actual behavior
The request just hangs in the client as there is no connection. The request promises never completes.
System configuration
- FeathersJS project generated by CLI to use:
- Express
- MongoDB
- Authentication set up via CLI
 
- Angular Frontend
Module versions (especially the part that's not working): "@feathersjs/adapter-commons": "^5.0.8", "@feathersjs/authentication": "^5.0.8", "@feathersjs/authentication-client": "^5.0.8", "@feathersjs/authentication-local": "^5.0.8", "@feathersjs/authentication-oauth": "^5.0.8", "@feathersjs/cli": "^5.0.8", "@feathersjs/configuration": "^5.0.8", "@feathersjs/errors": "^5.0.8", "@feathersjs/express": "^5.0.8", "@feathersjs/feathers": "^5.0.8", "@feathersjs/mongodb": "^5.0.8", "@feathersjs/rest-client": "^5.0.8", "@feathersjs/schema": "^5.0.8", "@feathersjs/socketio": "^5.0.8", "@feathersjs/transport-commons": "^5.0.8", "@feathersjs/typebox": "^5.0.8", "compression": "^1.7.4", "mongodb": "^5.7.0", "winston": "^3.10.0"
NodeJS version: v18.16.0
Operating System: MacOS
Browser Version: Chrome 114 Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36
Related Tickets
https://github.com/feathersjs/feathers/issues/2194 https://github.com/feathersjs/feathers/issues/2194#issuecomment-762419223 https://github.com/feathersjs/feathers/issues/2194#issuecomment-762562893
Thanks in advance for your review!
This should be doable with the manual reconnection mentioned in the Socket.io documentation:
socket.on('disconnect', () => {
  socket.connect()
})
Ran into this problem early on in a React Native client. I never understood the purpose of the server disconnecting the socket at the moment of token expiration, causing you have to write your own reconnect logic on the clients...I got it mostly working but the edge cases became too much to overcome. Auto reconnect already worked great out of the box with socketio.
I ended up patching handleConnection in the authentication package by removing the emit('disconnect') call and the long timer setup/teardown and implementing a simple token expiry check on the client.