We are using the @microsoft/signalr JavaScript client in our Vue frontend to establish a websocket connection with our backend (.net core). Also, we use a Bearer token for authentication.
This is the connection builder in the frontend:
this.connection = new HubConnectionBuilder()
.withUrl('/chat', { accessTokenFactory: () => IdService.getToken() })
.configureLogging(LogLevel.Information)
.withAutomaticReconnect()
.build()
Then I start the connection in this code:
HubService.connection.start().then(() => {
console.log('Connection started')
}).catch(err => {
console.error(err)
})
My problem is, when the Bearer token expires in the backend, on a reconnect I get a 401 error in the frontend, which is correct and I want to respond correctly to this error. I can catch the error in the catch block of the start function but I don't know how to handle the error, because I can't read a status code from the request like in a normal HTTP request. Its just a error message from the signalr client. Of course I could search in the string for '401' but that seems wrong.
Error: Failed to start the connection: Error: Failed to complete negotiation with the server: Error: Unauthorized: Status code '401'
I would like to know where in my code and how to properly handle this type of error and other errors to. Any help or ideas are appreciated.
The correct way to to this is your IdService.getToken() get you a refreshed token when it is almost expires because it's said in the Microsoft documentation that this function is called every time that there is an communication from client to hub.
The access token function you provide is called before every HTTP request made by SignalR. If you need to renew the token in order to keep the connection active (because it may expire during the connection), do so from within this function and return the updated token.
There are many examples for the token providers to refresh the token when it is near expiration.
But if that fix/implementation is out of your reach/control, the only thing you can do is catch the exception and just initialize again the connection. Something like this:
But this is a workaround to the original problem, that is the proper token refresh function.