Base solution for your next web application
Open Closed

OnlineClient is being created with null tenant id and user id on reconnect in certain situations #11777


User avatar
0
harley.mcphee created

It seems when the access token is expired and signalr reconnects to our back-end, the TenantId and UserId is null when CreateClientForCurrentConnection is called.

During debugging, I checked AuthConfigurer.SetToken and it's still being sent the old expired access token, it seems the front-end is not updating the signalr object with the new refreshed access token stored in local storage, I debugged the front-end as well and when I inspect the connection object I can see that connection.qs still has the expired access token. When I refresh the browser this fixes it though, so I am guessing this is why the TenantId and UserId is null when a client reconnects, because the access token is no longer valid. Any idea on how to fix this?

I have been trying to update the access token in the connection but no luck, how can I fix this? We have front-ends that are connected for days without refreshing and sometimes we update the back-end or restart the server and this causes the client to reconnect but now when they reconnect they don't have a TenantId or ClientId so they are not getting the messages that they should be

import { Injectable, Injector, NgZone } from '@angular/core'; import { AppComponentBase } from '@shared/common/app-component-base'; import { HubConnection } from '@microsoft/signalr'; import { AppConsts } from '@shared/AppConsts'; import { LocalStorageService } from '@shared/utils/local-storage.service'; import { SignalRHelper } from '@shared/helpers/SignalRHelper';

@Injectable() export class TimerSignalrService extends AppComponentBase { timerHub: HubConnection; isConnected = false;

constructor(injector: Injector, public _zone: NgZone) {
    super(injector);
}

configureConnection(connection): void {
    // Set the common hub
    this.timerHub = connection;

    // Reconnect loop
    let reconnectTime = 5000;
    let tries = 1;
    function start() {
        return new Promise(function (resolve) {

            new LocalStorageService().getItem(AppConsts.authorization.encrptedAuthTokenName, function (err, value: {token: string, expireDate: string}) {

                if (new Date(value.expireDate) <= new Date()) {
                    console.log('Token expired, reconnecting in 5 seconds'); 
                    setTimeout(() => {
                        start().then(resolve);
                    }, 5000);
                    return;
                }

                SignalRHelper.updateEncryptedAuthToken(value.token);
                connection.qs = AppConsts.authorization.encrptedAuthTokenName + '=' + encodeURIComponent(value.token);

                /// this needs to be updated
                connection.connection.baseUrl = abp.appPath + 'signalr-timesheet?' + connection.qs;

                connection
                    .start()
                    .then(resolve)
                    .then(() => {
                        console.log('Reconnected on try ' + tries); // TODO: Remove console.log(
                        console.log('Reconnected with access token: ' + value.token); 
                        reconnectTime = 5000; // Reset reconnect time after a successful connection
                        tries = 1; // Reset tries after a successful connection
                    })
                    .catch(() => {
                        setTimeout(() => {
                            start().then(resolve);
                        }, reconnectTime);
                        console.log('Failed to reconnect on try ' + tries); // TODO: Remove console.log( (
                        tries += 1; // Increment tries
                    });

            });


        });
    }


    // Reconnect if hub disconnects
    connection.onclose((e) => {
        this.isConnected = false;

        if (e) {
            abp.log.debug('TimeSheet connection closed with error: ' + e);
        } else {
            abp.log.debug('TimeSheet disconnected');
        }

        start().then(() => {
            this.isConnected = true;
        });
    });

    // Register to get notifications
    this.registerTimerEvents(connection);
}

registerTimerEvents(connection): void {
    connection.on('getTimeEntry', (message) => {
        abp.event.trigger('app.timesheet.timeEntryUpdateReceived', message);
    });
}

init(): void {
    this._zone.runOutsideAngular(() => {
        abp.signalr.connect();
        abp.signalr
            .startConnection(abp.appPath + 'signalr-timesheet', (connection) => {
                console.log('Start connection to timesheet hub!'); // TODO: Remove console.log(
                this.configureConnection(connection);
            })
            .then(() => {
                console.log('Connected to time-sheet hub!'); // TODO: Remove console.log(
                abp.event.trigger('app.timesheet.connected');
                this.isConnected = true;
            });
    });
}

}


3 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @harley.mcphee

    This seems like a bug, could you create an issue on https://github.com/aspnetzero/aspnet-zero-core so we will fix it in the next version.

  • User Avatar
    0
    harley.mcphee created

    Okay here it is https://github.com/aspnetzero/aspnet-zero-core/issues/5057

  • User Avatar
    0
    ismcagdas created
    Support Team

    Thanks a lot, I have added it to v13.1 but I will try to include it to v13.0 final if possible.