Как авторизовать метод SignalR Core Hub с помощью JWT

Я использую аутентификацию JWT в своем приложении ASP.NET Core 2.0 с OpenIddict.

Я следую идее в этом потоке и вызываю метод AuthorizeWithJWT после рукопожатия SignalR. Но теперь я не знаю, что мне установить в AuthorizeWithJWT методе, чтобы я мог использовать, например, [Authorize(Roles="Admin")].

Я попытался настроить контекстного пользователя, но он доступен только для чтения:

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

И используя атрибут авторизации:

public class VarDesignImportHub : BaseHub
{
    [Authorize(Roles = "Admin")]
    public async Task Import(string ConnectionString)
    {
    }
}

person Makla    schedule 16.10.2017    source источник


Ответы (1)


Я настоятельно рекомендую вам продолжить аутентификацию на уровне рукопожатия вместо того, чтобы использовать индивидуальное и нестандартное решение, которое вы бы реализовали на уровне SignalR.

Предполагая, что вы используете обработчик проверки, вы можете заставить его получить токен доступа из строки запроса:

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

                return Task.CompletedTask;
            };
        });
}

Или OnMessageReceived, если вы хотите использовать 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;
            },
        };
    });

Никаких других изменений не требуется.

person Kévin Chalet    schedule 18.10.2017
comment
Да, это был бы допустимый случай, но, как объясняется в потоке github (link1, link2) при таком подходе есть некоторые риски безопасности. Поскольку access_token в запросе является общедоступным (вы можете его зарегистрировать ...). Сделаю это, если другой подход невозможен. - person Makla; 19.10.2017
comment
Но одноразовый токен доступа мог это сделать? @Pinpoint Что ты думаешь? - person Makla; 19.10.2017
comment
Единственный риск заключается в том, что токен доступа будет включен в журналы (что четко объяснено в спецификации носителя OAuth2). Чтобы этого избежать, вы можете отключить трассировку журналов, включая строку запроса, с помощью API фильтрации. - person Kévin Chalet; 19.10.2017