首页 > 解决方案 > 如何使用 Auth0 和 JWT 限制特定角色的 aspnet 核心操作

问题描述

我正在使用 React 创建一个 PWA,并使用 Auth0 作为我的身份提供者和 JWT Bearer 令牌作为身份验证。我将角色注入到我的 JWT 令牌中,以便客户端可以限制用户可用的选项,并且我的工作非常好。

我现在想限制服务器端,以便除非用户具有访问该端点所需的必要角色,否则无法调用端点。

令人讨厌的是,Auth0 似乎不支持添加rolesrole声称 aspnet 核心似乎可以处理 OOTB;它要求域以声明定义中的角色开头。即,https://bob.com/roles作为索赔。

我正在尝试弄清楚如何获得Authorize(Roles = "Administrator")属性以尊重以域开头的角色声明。

我尝试更新 Auth0 规则以设置roleorroles属性,但这些永远不会被返回;只有域前缀角色声明似乎回归。

我找到了有关更具体的身份验证提供程序的其他信息,它们包含一个MapJsonKey扩展ClaimActions,看起来很符合要求,但扩展中的标准AuthenticationOptions对象AddAuthentication似乎没有这个。

我在 App.cs 中的 ConfigureServices

public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            // 1. Add Authentication Services
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(options =>
            {
                options.Authority = Configuration["Auth0:Authority"];
                options.Audience = Configuration["Auth0:ClientId"];
            });

            // In production, the React files will be served from this directory
            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/build";
            });
        }

我在 Auth0 中将角色注入 JWT 的规则:

function (user, context, callback) {
  const namespace = 'http://bob.com';
  const assignedRoles = (context.authorization || {}).roles;

  let idTokenClaims = context.idToken || {};
  let accessTokenClaims = context.accessToken || {};

  idTokenClaims[`roles`] = assignedRoles; // This was an attempt to set the roles in 'roles' but doesn't get returned.
  accessTokenClaims[`roles`] = assignedRoles;

  idTokenClaims[`${namespace}/roles`] = assignedRoles; // This does get returned
  accessTokenClaims[`${namespace}/roles`] = assignedRoles;

  context.idToken = idTokenClaims;
  context.accessToken = accessTokenClaims;
  callback(null, user, context);
}

示例 JWT 有效负载

{
    "http://bob.com/roles": [
        "Administrator"
    ],
    "given_name": "Name",
    "iss": "{issuer}",
    "sub": "{subject}",
    "aud": "{audience}"
}

asp.net core Action(取自示例项目,但添加了身份验证)

[HttpGet("[action]"), Authorize(Roles = "Administrator")]
        public IEnumerable<WeatherForecast> WeatherForecasts()
        {
            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                DateFormatted = DateTime.Now.AddDays(index).ToString("d"),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            });
        }

我想要的是能够将 映射http://bob.com/rolesroles,获取 aspnet 核心Authorize属性以查看http://bob.com/roles,或者让 Auth0 能够返回“角色”对象中的角色。

我从哪里获得MapJsonKey信息: https ://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/additional-claims?view=aspnetcore-2.2

将角色与 ASP.NET Core JWT 中间件一起使用 https://www.jerriepelser.com/blog/using-roles-with-the-jwt-middleware/

标签: jwtrolesauth0asp-net-core-spa-services

解决方案


对于发现此问题的任何人,我找到了解决方案。如果您更新 JWT 声明,http://schemas.microsoft.com/ws/2008/06/identity/claims/role那么一切都会立即生效。

更新了 Auth0 规则

function (user, context, callback) {
  const assignedRoles = (context.authorization || {}).roles;

  let idTokenClaims = context.idToken || {};
  let accessTokenClaims = context.accessToken || {};

  idTokenClaims[`http://schemas.microsoft.com/ws/2008/06/identity/claims/role`] = assignedRoles;
  accessTokenClaims[`http://schemas.microsoft.com/ws/2008/06/identity/claims/role`] = assignedRoles;

  context.idToken = idTokenClaims;
  context.accessToken = accessTokenClaims;
  callback(null, user, context);
}

推荐阅读