使用多个JWT承载认证

时间:2018-04-06 13:51:33

标签: firebase-authentication asp.net-core-mvc jwt 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
                };
        }

我可以拥有多个发卡人和受众,但我无法设置多个权限。

2 个答案:

答案 0 :(得分:47)

你可以完全达到你想要的效果:

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();
    });

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

AddAuthentication没有参数

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

使用AddJwtBearer

的另一个重载

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

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

更新默认策略

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

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

这并不能阻止你对某些行为采取更严格的限制; Custom属性具有AuthenticationSchemes属性,允许您覆盖哪些身份验证方案有效。

如果您有更复杂的方案,则可以使用policy-based authorization。我发现官方文档很棒。

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

[Authorize]

然后,您可以对某些操作使用// 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()); });

答案 1 :(得分:5)

这是MickaëlDerriey回答的扩展。

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

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());
});