使用多个JWT承载认证

San*_*ane 46 jwt asp.net-core-mvc firebase-authentication asp.net-core-2.0

是否有可能在ASP.NET Core 2中支持多个JWT令牌发行者?我想为外部服务提供API,我需要使用两个JWT令牌源 - Firebase和自定义JWT令牌发行者.在ASP.NET核心中,我可以为Bearer身份验证方案设置JWT身份验证,但仅限于一个权限:

  services
        .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.Authority = "https://securetoken.google.com/my-firebase-project"
            options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidIssuer = "my-firebase-project"
                    ValidateAudience = true,
                    ValidAudience = "my-firebase-project"
                    ValidateLifetime = true
                };
        }
Run Code Online (Sandbox Code Playgroud)

我可以有多个发行人和受众,但我不能设置多个权限.

Mic*_*iey 94

你可以完全实现你想要的:

services
    .AddAuthentication()
    .AddJwtBearer("Firebase", options =>
    {
        options.Authority = "https://securetoken.google.com/my-firebase-project"
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuer = "my-firebase-project"
            ValidateAudience = true,
            ValidAudience = "my-firebase-project"
            ValidateLifetime = true
        };
    })
    .AddJwtBearer("Custom", options =>
    {
        // Configuration for your custom
        // JWT tokens here
    });

services
    .AddAuthorization(options =>
    {
        options.DefaultPolicy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("Firebase", "Custom")
            .Build();
    });
Run Code Online (Sandbox Code Playgroud)

让我们来看看你的代码与那个代码之间的差异.

AddAuthentication 没有参数

如果设置了默认身份验证方案,则在每个请求中,身份验证中间件将尝试运行与默认身份验证方案关联的身份验证处理程序.由于我们现在有两种可视认证方案,因此运行其中一种方案毫无意义.

使用另一个重载 AddJwtBearer

AddXXX添加身份验证的每种方法都有几个重载:

现在,因为您使用相同的身份验证方法两次但身份验证方案必须是唯一的,您需要使用第二个重载.

更新默认策略

由于请求将不再自动进行身份验证,[Authorize]因此对某些操作设置属性将导致请求被拒绝并将HTTP 401发出请求.

由于这不是我们想要的,因为我们希望为身份验证处理程序提供对请求进行身份验证的机会,因此我们通过指示应尝试验证请求Firebase以及Custom身份验证方案来更改授权系统的默认策略.

这并不妨碍您对某些行为采取更严格的限制措施; 该[Authorize]属性具有一个AuthenticationSchemes属性,允许您覆盖哪些身份验证方案有效.

如果您有更复杂的方案,则可以使用基于策略的授权.我发现官方文档很棒.

让我们假设某些操作仅适用于Firebase发布的JWT令牌,并且必须具有特定值的声明; 你可以这样做:

// Authentication code omitted for brevity

services
    .AddAuthorization(options =>
    {
        options.DefaultPolicy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("Firebase", "Custom")
            .Build();

        options.AddPolicy("FirebaseAdministrators", new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("Firebase")
            .RequireClaim("role", "admin")
            .Build());
    });
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用[Authorize(Policy = "FirebaseAdministrators")]某些操作.

  • 这是一个非常有帮助的答案,它将我在各处看到的很多内容整合在一起。 (21认同)
  • 你好。正在寻找这个解决方案。不幸的是,我收到“未指定身份验证方案,并且未找到 DefaultChallengeScheme”异常。options.DefaultPolicy 设置正常。有任何想法吗? (9认同)
  • 这是否需要从 firebase 或自定义解决方案更改标头值?IE。例如,而不是`Authorization : Bearer <token>` 标题是`Authorization : Firebase <token>`?尝试此解决方案时,我收到错误消息:“没有为方案‘承载’注册身份验证处理程序。” (8认同)
  • 不,标题不需要更改。该错误消息表明您指的是不存在的身份验证方案 (Bearer)。在我们的示例中,两个注册的方案是 Firebase 和 Custom,它们是 `.AddJwtBearer` 方法调用的第一个参数。 (5认同)
  • @TylerOhlsen 这是不正确的;虽然它会在您描述的情况下使用,但它并不是唯一的一种。如果您没有在端点级别指定授权要求,而是使用空的“[Authorize]”属性装饰 MVC 控制器和/或操作,也将使用它。 (3认同)

No *_*rns 6

这是 Mickaël Derriey 答案的延伸。

我们的应用程序有一个自定义授权要求,我们从内部来源解决了该要求。我们使用的是 Auth0,但正在使用 OpenID 切换到 Microsoft 帐户身份验证。这是我们的 ASP.Net Core 2.1 Startup 中稍微编辑过的代码。对于未来的读者,这适用于指定的版本。调用方在作为不记名令牌传递的传入请求上使用来自 OpenID 的 id_token。希望它可以帮助其他人尝试进行身份权限转换,就像这个问题和答案对我的帮助一样。

const string Auth0 = nameof(Auth0);
const string MsaOpenId = nameof(MsaOpenId);

string domain = "https://myAuth0App.auth0.com/";
services.AddAuthentication()
        .AddJwtBearer(Auth0, options =>
            {
                options.Authority = domain;
                options.Audience = "https://myAuth0Audience.com";
            })
        .AddJwtBearer(MsaOpenId, options =>
            {
                options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                {
                    ValidateAudience = true,
                    ValidAudience = "00000000-0000-0000-0000-000000000000",

                    ValidateIssuer = true,
                    ValidIssuer = "https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0",

                    ValidateIssuerSigningKey = true,
                    RequireExpirationTime = true,
                    ValidateLifetime = true,
                    RequireSignedTokens = true,
                    ClockSkew = TimeSpan.FromMinutes(10),
                };
                options.MetadataAddress = "https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0/.well-known/openid-configuration";
            }
        );

services.AddAuthorization(options =>
{
    options.DefaultPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .AddAuthenticationSchemes( Auth0, MsaOpenId )
        .Build();

    var approvedPolicyBuilder =  new AuthorizationPolicyBuilder()
           .RequireAuthenticatedUser()
           .AddAuthenticationSchemes(Auth0, MsaOpenId)
           ;

    approvedPolicyBuilder.Requirements.Add(new HasApprovedRequirement(domain));

    options.AddPolicy("approved", approvedPolicyBuilder.Build());
});
Run Code Online (Sandbox Code Playgroud)