为由中间件处理的单个路由指定身份验证方案

Specifying an authentication scheme for a single route that's handled by middleware

我有一个新的 ASP.Net Core 3 MVC 站点,我已使用 HotChocolate 添加了 GraphQL。我有用户使用基于 cookie 的身份验证和 Auth0 登录到 MVC 端:

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 身份验证允许使用 GQL。但是我不知道如何为 /graphql 路由获取控制器的 cookie 授权和 JWT。

一点上下文:HotChocolate 使用自定义中间件来处理进入 /graphql 路由的请求。它不在控制器上,所以我不能只使用 Authorize 属性指定方案,因为没有控制器可以安装它。

类似问题

(还有一些其他的,主要集中在结合 REST 和 MVC,但是这些都去控制器所以场景有点不同。)

我不知道该怎么做。我最终只是将它分成两个项目。一个提供 GraphQL API,另一个提供网站。这样做,每个人都可以有自己的身份验证方案。

我遇到了同样的问题,所以我想 post 我的解决方案以防其他人遇到同样的问题。

Hot Chocolate 使用默认身份验证方案,因此在启动时我将 JWT 声明为默认方案:

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

    })

在任何需要 Cookie 身份验证的地方,我只需添加:

[Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]

我有一个非常相似的问题,我想分享我的解决方案。就我而言,我希望将两种身份验证模式都应用于我的 HotChocolate api。通过添加以下属性,我能够为普通控制器端点执行此操作:

[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";
            });

从上面 IgnacioMir 的回答中得到灵感,我想我终于找到了一种相当优雅的方法。

假设您希望对网站的大部分内容使用 Cookie 身份验证,但对 Hot Chocolate 端点使用其他一些方案(例如 JWT 不记名令牌),那么您可以像往常一样将 Cookie 身份验证作为默认设置来定义身份验证方案:

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

然后将 AuthorizeAttribute and an AllowAnonymousAttribute 添加到 GraphQL 端点:

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

这会覆盖 GraphQL 端点的默认身份验证方案,而不会 ASP.NET 强制执行任何授权检查。

换句话说,AllowAnonymousAttribute 确保授权检查留给 HotChocolate 自己的授权中间件,如果您只想将检查应用于标记为 HotChocolate AuthorizeAttribute 的字段,这一点尤为重要.