3

I am using JWT authentication in my ASP.NET Core 2.0 application with OpenIddict.

I am following idea in this thread and calling AuthorizeWithJWT method after SignalR handshake. But now, I do not know what should I set in AuthorizeWithJWT method so I can use [Authorize(Roles="Admin")] for example.

I tried with setting context user, but it is readonly:

public class BaseHub : Hub
{    
    public async Task AuthorizeWithJWT(string AccessToken)
    {
        //get user claims from AccesToken
        this.Context.User = user;  //error User is read only
    }
}

And using authorize attribute:

public class VarDesignImportHub : BaseHub
{
    [Authorize(Roles = "Admin")]
    public async Task Import(string ConnectionString)
    {
    }
}
Makla
  • 9,899
  • 16
  • 72
  • 142

1 Answers1

7

I strongly encourage you to continue doing authentication at the handshake level instead of going with a custom and non-standard solution you'd implement at the SignalR level.

Assuming you're using the validation handler, you can force it to retrieve the access token from the query string:

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication()
        .AddOAuthValidation(options =>
        {
            options.Events.OnRetrieveToken = context =>
            {
                context.Token = context.Request.Query["access_token"];

                return Task.CompletedTask;
            };
        });
}

Or OnMessageReceived if you want to use JWTBearer:

services.AddAuthentication()
    .AddJwtBearer(o =>
    {
        o.Events = new JwtBearerEvents()
        {
            OnMessageReceived = context =>
            {
                if (context.Request.Path.ToString().StartsWith("/HUB/"))
                    context.Token = context.Request.Query["access_token"];
                return Task.CompletedTask;
            },
        };
    });

No other change should be required.

Makla
  • 9,899
  • 16
  • 72
  • 142
Kévin Chalet
  • 39,509
  • 7
  • 121
  • 131
  • Yes this would be a valid case, but as explain in github thread ([link1](https://github.com/aspnet/SignalR/issues/888#issuecomment-330727192), [link2](https://github.com/aspnet/SignalR/issues/888#issuecomment-330721385)) there are some security risks with this approach. Because access_token in query is public (you can log it...). Will do that, if no other approach is possible. – Makla Oct 19 '17 at 10:33
  • But one time access token could do it? @Pinpoint What do you think? – Makla Oct 19 '17 at 10:39
  • 1
    The only "risk" is that the access token will be included in the logs (which is clearly explained in the OAuth2 bearer specification). To avoid that, you could disable the logging traces including the query string using the filtering API. – Kévin Chalet Oct 19 '17 at 14:42