首页 > 解决方案 > 在使用来自外部提供者的 ASP.NET 身份和 JWT 身份验证时,我可以使用角色和声明的授权属性过滤吗?

问题描述

所以我在我的 WebAPI 应用程序上使用 firebase 进行身份验证。它获取一个 JWT 令牌,然后对其进行身份验证,然后将声明放入HttpContext.User.

我唯一的问题是我只想使用 Firebase 身份验证进行身份验证,而不是授权。我想为此使用 ASP.NET Identity。

所以现在,当有人连接到我的服务器时,我会检查他们是否没有帐户,如果没有,我会为他们创建一个。

var name = _contextAccessor.HttpContext.User.Claims.First(c => c.Type == "user_id").Value;

ApplicationUser user = await _userManager.FindByNameAsync(name);

if (user == null)
{
    user = new ApplicationUser(name);
    await _userManager.CreateAsync(user);                
}

所以这是可行的,现在 ASPNetUsers 中有一个针对用户的记录,稍后,我可以根据我想要的任何业务规则为其提供声明和角色。

但是,我的问题是,以前,当我使用 ASP.NET Identity 时,我已经能够利用 Authorize 属性等所有内置功能来进行授权。

因此,如果身份验证和授权都使用 ASP.NET Identity 完成,我可以编写

[Authorize(Roles = "Administrator")]

显然,这不适用于外部身份验证,因为HttpContext.User是 Firebase Authenticated 用户,而不是具有管理员角色的相应 ASP.NET 身份用户。

有没有办法自定义现有的 Authorize 属性以将其配置为以某种方式将我的 firebase 令牌转换为 ASP.NET 身份,以便它能够识别角色并声称它具有,或者如果我想通过中间件来完成所有这些,我会去吗需要编写我自己的授权属性吗?

标签: c#asp.net-corejwtasp.net-core-webapiasp.net-core-2.2

解决方案


好的,所以我终于想通了。在 Jwt 身份验证过程中,您似乎可以拦截几个事件。特别是,有一个 OnTokenValidated 事件。

services.AddJwtBearer(options =>
{
    ...

    options.Events = new JwtBearerEvents
    {

        OnTokenValidated = async ctx =>
        {
            // 1. grabs the user id from firebase
            var name = ctx.Principal.Claims.First(c => c.Type == "user_id").Value;

            // Get userManager out of DI
            var _userManager = ctx.HttpContext.RequestServices.GetRequiredService<UserManager<ApplicationUser>>();

            // 2. retrieves the roles that the user has
            ApplicationUser user = await _userManager.FindByNameAsync(name);
            var userRoles = await _userManager.GetRolesAsync(user);

            //3.  adds the role as a new claim 
            ClaimsIdentity identity = ctx.Principal.Identity as ClaimsIdentity;
            if (identity != null)
            {
                foreach (var role in userRoles)
                {
                    identity.AddClaim(new System.Security.Claims.Claim(ClaimTypes.Role, role));
                }
            }

        }

    };
});

那么上面的代码在说什么

  1. 令牌通过身份验证后,从外部提供者处获取 userId
  2. 进入 ASP.NET Identity 并找到该用户的用户和角色 [记住我最初的问题,当他们第一次登录时,我将用户插入到 ASP.NET Identity 表中,我只是抓住了那个用户]

  3. 将该用户的角色重新插入到 ClaimsIdentity

结果是,当 Authorize 属性运行时,它会在检查中包含用户的 AspNET 身份角色,我可以执行以下操作,它会检查角色。

[Authorize(Roles = "Administrator")]

推荐阅读