AddJwtBearer 的动态权限

问题描述 投票:0回答:1

我有一个使用 KeyCloak 作为身份代理的多租户应用程序。 token中有TenantId,通过它我们就可以识别出是哪个Tenant的用户。 现在,在验证令牌时,我们使用 AddJwtBearer 和 Authority。 我希望根据 TenantId 从配置中获取该权限。

有什么办法可以实现这个目标吗?

public static class KeycloakAuthenticationExtensions
{
    public static void AddKeycloakAuthentication(this IServiceCollection services, IConfiguration configuration)
    {
        var jwtConfiguration = configuration.GetSection(Core.Authentication.Constants.JwtConfigurationSection).Get<JwtConfiguration>();

        services.AddOptions<JwtConfiguration>().Bind(configuration.GetSection(Authentication.Constants.JwtConfigurationSection));
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

        }).AddJwtBearer(options =>
        {
            options.Authority = jwtConfiguration!.Authority;
            options.SaveToken = false;
            options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
            {
                ValidAudiences = jwtConfiguration.Audiences,
                ValidateAudience = true,
                ValidateIssuer = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                //https://learn.microsoft.com/en-us/aspnet/core/security/authentication/claims?view=aspnetcore-6.0#extend-or-add-custom-claims-using-iclaimstransformation
                //Name claim and role claim mapping
                NameClaimType = ApiConstants.PreferredUserNameClaim
            };

            options.Events = new JwtBearerEvents()
            {
                OnMessageReceived = context =>
                {
                    return Task.CompletedTask;
                },
                OnAuthenticationFailed = context =>
                {
                    context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                    return context.Response.WriteAsync(context.Request.Headers[ApiConstants.AuthorizationHeader].ToString());
                },
                OnTokenValidated = context =>
                {
                    return Task.CompletedTask;
                }
            };

        });
        services.AddSingleton<ITokenProvider, KeyCloakJwtTokenProvider>();
        services.AddSingleton<ITokenStore, InMemoryCachedTokenStore>();
        services.AddTransient<AuthenticationHttpMessageHandler>();
        services.AddHttpClient<ITokenProvider, KeyCloakJwtTokenProvider>(client =>
        {
            client.BaseAddress = new Uri(jwtConfiguration!.Authority + ApiConstants.TokenEndpoint);
        });
    }
}

我已将 jwtConfiguration 更改为租户信息列表。

对于每个请求,都会调用 AddJwtBearer 来验证令牌。根据作为令牌一部分的租户 ID,我想设置权限并验证令牌。 我期待如下所示的内容,我将能够获取 TenantId 并从配置中存储的租户列表中获取租户信息

    services.AddOptions<TenantConfiguration>().Bind(configuration.GetSection(Authentication.Constants.TenantConfiguration));
    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    }).AddJwtBearer(options =>
    {
        var tenant1 = jwtConfiguration!.TenantInfo.FirstOrDefault(x => x.TenantId.Equals("**tenantId**", StringComparison.OrdinalIgnoreCase));
        options.Authority = royHillTenant?.Authority;
        options.SaveToken = false;
        options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
        {
            ValidAudiences = royHillTenant?.Audiences,
            ValidateAudience = true,
            ValidateIssuer = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            //https://learn.microsoft.com/en-us/aspnet/core/security/authentication/claims?view=aspnetcore-6.0#extend-or-add-custom-claims-using-iclaimstransformation
            //Name claim and role claim mapping
            NameClaimType = ApiConstants.PreferredUserNameClaim
        };

        options.Events = new JwtBearerEvents()
        {
            OnMessageReceived = context =>
            {
                return Task.CompletedTask;
            },
            OnAuthenticationFailed = context =>
            {
                context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                return context.Response.WriteAsync(context.Request.Headers[ApiConstants.AuthorizationHeader].ToString());
            },
            OnTokenValidated = context =>
            {
                return Task.CompletedTask;
            }
        };

    });
    services.AddSingleton<ITokenProvider, KeyCloakJwtTokenProvider>();
    services.AddSingleton<ITokenStore, InMemoryCachedTokenStore>();
    services.AddTransient<AuthenticationHttpMessageHandler>();
    services.AddHttpClient<ITokenProvider, KeyCloakJwtTokenProvider>();// client =>
    //{
    //    client.BaseAddress = new Uri(jwtConfiguration!.Authority + ApiConstants.TokenEndpoint);
    //});
}
asp.net-core authentication oauth jwt keycloak
1个回答
0
投票

您可以稍后在控制器或自定义中间件中使用

IOptionsMonitor
更改任何服务选项。尝试以下修改控制器中的选项

    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        private readonly IServiceProvider _provider;

        public ValuesController(IServiceProvider provider)
        {
            this._provider = provider;
        }
        [HttpGet("test")]
        public void Test()
        {
            var jwtoptionsMonitor = _provider.GetService<IOptionsMonitor<JwtBearerOptions>>();
            var jwtoptions = jwtoptionsMonitor.Get(JwtBearerDefaults.AuthenticationScheme);

            //then you can modify jwtoptions as you like
            jwtoptions.Authority = "new value";
            jwtoptions.TokenValidationParameters.ValidAudience = "new value";

        }
    }

(注意:只有使用注入Iserviceprovider来获取IoptionsMonitor才有效。如果直接注入IOptionsMonitor,则不起作用。)

© www.soinside.com 2019 - 2024. All rights reserved.