使用 AddJwtBearer() 和基于自定义角色的属性在 .NET 8 中实现 JWT 令牌授权

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

我从 SPA 收到不记名 JWT 访问令牌,我需要验证此 JWT 令牌,但也需要使用其中的角色声明。角色声明当前使用字段“user-roles”:“admin,usertype2”。因此,角色类型在“用户角色”中以逗号分隔(如果这更容易,我也许可以让我们的 Okta 团队将其更改为字符串数组,但目前这就是实现)。我已经构建了一个自定义属性来尝试处理授权,但我想使用标准 MS 库来完成这项工作。我的program.cs中有以下内容:

builder.Services.AddAuthentication().AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        RoleClaimType = "user-roles"
    };
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseRateLimiter();
app.UseStaticFiles();
app.UseCors("MyPolicy");
app.UseAuthorization();
app.MapControllers();

app.Run(); 

然后对于我的实施,我尝试了以下操作:

    [HttpGet(Name = "GetUserAccount")]
    [Authorize(Roles = "usertype1,usertype2")]
    [EnableRateLimiting("api")]
    public IActionResult Get()
    {
        User TestAccount = new User() {InternalUserNumber = 3, EmailAddress = "[email protected]"};
        var json = _userAccountService.Read(TestAccount);
        return Ok(json);
    }

我认为在 AddJwtBearer() 函数的选项中设置 RoleClaimType = "user-roles" 将允许在声明中设置要查找的自定义字段,但似乎并没有这样做。我不确定如何设置自定义角色字段,也不清楚如何将字符串分割(),以便它可以检查这些角色实际上在声明中的相交。

asp.net-core jwt okta
1个回答
0
投票

为了使用属性通过 AddJwtBearer() 进行声明检查,可以使用以下方法:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.IdentityModel.Tokens;

namespace ARMS_API.Filters
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class OktaAllowedRoles : Attribute, IAuthorizationFilter
    {
        private readonly string[] _allowedRoles;
        public OktaAllowedRoles(string[] AllowedRoles)
        {
            _allowedRoles = AllowedRoles;
        }
        public void OnAuthorization(AuthorizationFilterContext context)
        {
            var claim = context.HttpContext.User.Claims.Where(claim => claim.Type.ToString() == "roles").FirstOrDefault();

            if(claim == null){
               context.Result = new UnauthorizedObjectResult(string.Empty);
               return;
            }
            else{
                var ClaimRoles =  claim.Value.Split(',');
                if(ClaimRoles.Intersect(_allowedRoles!).ToArray().IsNullOrEmpty())
                {
                    context.Result = new UnauthorizedObjectResult(string.Empty);
                    return;
                }
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.