IdentityModel / IdentityModel.AspNetCore.OAuth2Introspection

ASP.NET Core authentication handler for OAuth 2.0 token introspection
Apache License 2.0
147 stars 66 forks source link

SignalR and OAuth2Introspection #188

Closed iburleigh closed 9 months ago

iburleigh commented 9 months ago

It seems like there is an issue when combining this with SignalR since you need to pull the access token out of the query string for SignalR to work. With normal .AddJWTBearer authorization you would pull the access token via the OnMessageReceived event. Here it seems like we are failing authorization before we hit any of the Auth2IntrospectionEvents to pull the token out.

brockallen commented 9 months ago

Yes, you are correct. The JwtBearer handler is not designed for WebSockets (SignalR) clients.

Microsoft doesn't really provide much guidance here, but what I've seen and used in the past is to use an authentication cookie (via Microsoft's cookie authentication handler) for your WebSocket connections. How you bootstrap that, though, could be done in a variety of ways depending on your app's architecture. It's also not without issues depending on what and how you go about it.

iburleigh commented 9 months ago

Thanks for the reply! Are we talking about the jwtbearer specifically in this library? The Microsoft.AspNetCore.Authentication.JwtBearer library works fine with SignalR as I have production apps running with it. The trick there is the OnMessageReceived event pulls the access token from the query string when accessing hubs per SignalR's recommendation. I'm mostly curious if it is or should be possible with this library.

brockallen commented 9 months ago

The Microsoft.AspNetCore.Authentication.JwtBearer library works fine with SignalR as I have production apps running with it.

Well... there's a lot of history of why this is forbidden in OAuth. So I never recommend putting the access token in a query param, even though you can technically "get it to work". That's why I recommended a different approach via an endpoint that in essence exchanged the token for a cookie for the WebSocket requests.

I'm mostly curious if it is or should be possible with this library.

Yes, there is a TokenRetriever func on the options. But as I mentioned above... :)

iburleigh commented 9 months ago

Thanks again! This was really helpful. There are ways around the security concerns from OAuth especially for intranet apps. If someone else is curious I got this working by setting the TokenRetriever to a new Custom TokenRetriever Class where we check to see if the route matches the SignalR hub route and pull from the query_string if it does, otherwise it follows the normal TokenRetriever logic. Sounds like I might need to use cookies in the future though.