From 9db5e7adb0f6aea43d607f530d8258ade98b7362 Mon Sep 17 00:00:00 2001 From: David Luecke Date: Sun, 27 Nov 2022 09:28:29 -0800 Subject: [PATCH] fix(authentication-client): Improve socket reauthentication handling (#2895) --- packages/authentication-client/src/core.ts | 18 ++++------- .../test/integration/socketio.test.ts | 30 +++++++++++++++++++ 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/packages/authentication-client/src/core.ts b/packages/authentication-client/src/core.ts index 916a9861cc..01c99c0da1 100644 --- a/packages/authentication-client/src/core.ts +++ b/packages/authentication-client/src/core.ts @@ -67,18 +67,12 @@ export class AuthenticationClient { } handleSocket(socket: any) { - // Connection events happen on every reconnect - const connected = this.app.io ? 'connect' : 'open' - const disconnected = this.app.io ? 'disconnect' : 'disconnection' - - socket.on(disconnected, () => { - const authPromise = new Promise((resolve) => socket.once(connected, (data: any) => resolve(data))) - // Only reconnect when `reAuthenticate()` or `authenticate()` - // has been called explicitly first - // Force reauthentication with the server - .then(() => (this.authenticated ? this.reAuthenticate(true) : null)) - - this.app.set('authentication', authPromise) + // When the socket disconnects and we are still authenticated, try to reauthenticate right away + // the websocket connection will handle timeouts and retries + socket.on('disconnect', () => { + if (this.authenticated) { + this.reAuthenticate(true) + } }) } diff --git a/packages/authentication-client/test/integration/socketio.test.ts b/packages/authentication-client/test/integration/socketio.test.ts index dc5f0789a7..da4bd2e7cd 100644 --- a/packages/authentication-client/test/integration/socketio.test.ts +++ b/packages/authentication-client/test/integration/socketio.test.ts @@ -7,6 +7,7 @@ import socketioClient from '@feathersjs/socketio-client' import authClient from '../../src' import getApp from './fixture' import commonTests from './commons' +import { AuthenticationResult } from '@feathersjs/authentication/lib' describe('@feathersjs/authentication-client Socket.io integration', () => { let app: Application @@ -52,6 +53,35 @@ describe('@feathersjs/authentication-client Socket.io integration', () => { assert.strictEqual(dummy.headers.authorization, `Bearer ${accessToken}`) }) + it('reconnects after socket disconnection', async () => { + const user = { email: 'disconnecttest@example.com', password: 'alsosecret' } + const socket = io('http://localhost:9777', { + timeout: 500, + reconnection: true, + reconnectionDelay: 100 + }) + const client = feathers().configure(socketioClient(socket)).configure(authClient()) + + await app.service('users').create(user) + await client.authenticate({ + strategy: 'local', + ...user + }) + + const onLogin = new Promise((resolve) => app.once('login', (data) => resolve(data))) + + socket.once('disconnect', () => socket.connect()) + socket.disconnect() + + const { + authentication: { strategy } + } = await onLogin + const dummy = await client.service('dummy').find() + + assert.strictEqual(strategy, 'jwt') + assert.strictEqual(dummy.user.email, user.email) + }) + commonTests( () => app, () => {