feat: Implement proactive access token refreshing within the session and reactive token renewal for socket authentication errors.

This commit is contained in:
pradeepkumar
2026-02-11 04:47:51 +05:30
parent 692a91f6db
commit 50e593d7ae
3 changed files with 120 additions and 13 deletions

View File

@@ -22,11 +22,15 @@ class SocketService {
private statusHandlers: Set<StatusHandler> = new Set();
private readHandlers: Set<ReadHandler> = new Set();
private connectionHandlers: Set<(connected: boolean) => void> = new Set();
private authErrorHandlers: Set<() => void> = new Set();
private isConnecting = false;
private currentToken: string | null = null;
connect(token: string): Promise<void> {
return new Promise((resolve, reject) => {
// Already connected
this.currentToken = token;
// Already connected with same token
if (this.socket?.connected) {
resolve();
return;
@@ -84,6 +88,12 @@ class SocketService {
console.log('Socket disconnected:', reason);
this.isConnecting = false;
this.notifyConnectionHandlers(false);
// "io server disconnect" means the server rejected us (likely auth failure)
if (reason === 'io server disconnect') {
console.warn('Socket: Server disconnected us (likely token expired). Requesting token refresh...');
this.authErrorHandlers.forEach((handler) => handler());
}
});
this.socket.on('connect_error', (error) => {
@@ -118,11 +128,26 @@ class SocketService {
});
}
// Reconnect with a fresh token (used when the previous token expired)
reconnectWithToken(token: string): void {
this.currentToken = token;
if (this.socket) {
// Update the auth token for reconnection
this.socket.auth = { token };
this.socket.connect();
} else {
this.connect(token).catch((err) => {
console.error('Socket reconnect with new token failed:', err);
});
}
}
disconnect(): void {
if (this.socket) {
this.socket.disconnect();
this.socket = null;
}
this.currentToken = null;
}
isConnected(): boolean {
@@ -225,6 +250,11 @@ class SocketService {
return () => this.connectionHandlers.delete(handler);
}
onAuthError(handler: () => void): () => void {
this.authErrorHandlers.add(handler);
return () => this.authErrorHandlers.delete(handler);
}
private notifyConnectionHandlers(connected: boolean): void {
this.connectionHandlers.forEach((handler) => handler(connected));
}