Azure / azure-signalr

Azure SignalR Service SDK for .NET
https://aka.ms/signalr-service
MIT License
427 stars 101 forks source link

Get the original AccessToken used for negotiation #1811

Closed WolfspiritM closed 1 year ago

WolfspiritM commented 1 year ago

Is your feature request related to a problem? Please describe.

My current workflow is like that:

This works so far. Now my SignalR Hub however needs to call other services using the users access token, however I can't seem to find a way to get the users original access token back and the token I can get is not the one my backend services are trusting. Without SignalR Services I can use the Authorize header coming from the gateway but the httpcontext obviously is not the same anymore when using signalr services. As my frontend also doesn't know the token it can't send the token via a method invocation.

Describe the solution you'd like

It would be nice if (maybe something like that exists but I wasn't able to find it?) there is a way to pass data from the negotation request to the actual hub context. I was thinking about memorycache but I guess that doesn't work as the service who sends the negotiation might not even be the service handling the hub context, right?

Is there any solution for that?

Y-Sindo commented 1 year ago

You could use the ServiceOptions.ClaimsProvider to set the original access token as a claim of the user during negotiation, then get it from SignalR hub context later.

builder.Services.AddSignalR().AddAzureSignalR(o => o.ClaimsProvider = httpContext => new Claim[] { new Claim("accessToken", httpContext.Request.Headers.Authorization) });

BTW, you may also want to utilize the ServiceOptions.ServerStickyMode to force the client to be routed to a server with whom it negotiates.

WolfspiritM commented 1 year ago

You could use the ServiceOptions.ClaimsProvider to set the original access token as a claim of the user during negotiation, then get it from SignalR hub context later.

Thanks. Adding the original access token to the claims as is would also mean that an attacker who gains xss access to the website context could theoretically "fake" a signalr authentication and then parse the signalr access token for the claims to get the original access token, right? Or is the access token encrypted? However using DataProtection to protect it before adding as a claim might work and I'll give it a try, I'm just a bit worried about the size of the resulting token

BTW, you may also want to utilize the ServiceOptions.ServerStickyMode to force the client to be routed to a server with whom it negotiates.

That way I could theoretically store the user access token based on the user id in memory for some time after negotiation and retrieve it once the connection comes from the signalr services. If the token size is a problem I think I'll move to this solution.

Thanks again! Going to close this issue as I don't see a way how this could be improved any further with how signalr services work.