Указание схемы аутентификации для одного маршрута, который обрабатывается промежуточным программным обеспечением

У меня есть новый сайт MVC ASP.Net Core 3, на который я добавил GraphQL с помощью HotChocolate. У меня есть пользователи, входящие в систему на стороне MVC, используя аутентификацию на основе файлов cookie с Auth0:

services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        })
    .AddCookie()
    .AddOpenIdConnect("Auth0", options =>
        {
            ...
        });

Но для запросов GraphQL мне нужна авторизация JWT, для которой я бы использовал:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(config =>
        {
            ...
        });

Они оба работают независимо друг от друга. Cookie auth позволяет использовать контроллер; JWT auth позволяет использовать GQL. Но я не могу понять, как получить аутентификацию cookie для контроллеров и JWT для/graphql маршрут.

Небольшой контекст: HotChocolate использует специальное промежуточное ПО для обработки запросов, поступающих в /graphqlмаршрут. Его нет на контроллере, поэтому я не могу просто указать схему сAuthorize атрибут, поскольку нет контроллера, на который можно было бы его надеть.

Похожие вопросы

(Было несколько других, в основном ориентированных на объединение REST и MVC, но они оба относятся к контроллерам, поэтому сценарий немного отличается.)

4 ответа

Решение

У меня была такая же проблема, поэтому я решил опубликовать свое решение на случай, если у других может быть такая же проблема.

Hot Chocolate использует схему аутентификации по умолчанию, поэтому в Startup я объявляю JWT по умолчанию:

          services.AddAuthentication(options =>
    {
        options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

    })

И везде, где мне нужна проверка подлинности файлов cookie, я просто добавляю:

      [Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]

У меня была похожая проблема, и я хотел поделиться своим решением. В моем случае я хотел, чтобы к моему API HotChocolate были применены обе схемы аутентификации. Я смог сделать это для обычных конечных точек контроллера, добавив следующие атрибуты:

      [Authorize(AuthenticationSchemes = "Bearer" + "," + "OpenIdConnect")]

Для того, чтобы обе схемы были применены к моей конечной точке HotChocolate graphql, я проделал этот трюк в моем Startup

             endpoints.MapGraphQL().RequireAuthorization()
            .Add((endpointBuilder) =>
            {
                var authAttribute = endpointBuilder.Metadata.SingleOrDefault(x =>
                    x is Microsoft.AspNetCore.Authorization.AuthorizeAttribute);
                if (authAttribute != null)
                    ((Microsoft.AspNetCore.Authorization.AuthorizeAttribute) authAttribute)
                        .AuthenticationSchemes = "Bearer" + "," +
                                                 "OpenIdConnect";
            });

Вдохновленный ответом ИгнасиоМира выше, я думаю, что наконец нашел то, что кажется достаточно элегантным способом сделать это.

Предполагая, что вы хотите использовать аутентификацию Cookie для большей части вашего сайта, но какую-то другую схему (например, токены носителя JWT) для конечной точки Hot Chocolate, вы можете определить свои схемы аутентификации с аутентификацией Cookie по умолчанию, как обычно:

      services
    .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie()
    .AddJwtBearer(...);

Затем добавьте обаик конечной точке GraphQL:

      app.MapGraphQL()
    .RequireAuthorization(new AuthorizeAttribute
    {
        AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme
    })
    .AllowAnonymous(); // Adds AllowAnonymousAttribute to the endpoint metadata

Это переопределяет схему проверки подлинности по умолчанию для конечной точки GraphQL без принудительной проверки авторизации ASP.NET.

Другими словами, AllowAnonymousAttributeгарантирует, что проверки авторизации оставлены собственному промежуточному программному обеспечению авторизации HotChocolate, что особенно важно, если вы хотите, чтобы проверки применялись только к полям, отмеченным HotChocolateAuthorizeAttribute.

Я не мог понять, как это сделать. В итоге я просто разделил его на два проекта. Один предоставляет GraphQL API, а другой предоставляет веб-сайт. При этом у каждого может быть своя собственная схема авторизации.

Другие вопросы по тегам