Auth0,带有授权扩展和 ASP.NET 授权

Posted

技术标签:

【中文标题】Auth0,带有授权扩展和 ASP.NET 授权【英文标题】:Auth0, with Authorization Extension & ASP.NET Authorization 【发布时间】:2019-02-04 05:59:44 【问题描述】:

我正在使用 Auth0 进行项目。我们希望使用授权扩展中的权限系统来设置它。

例如 角色管理员: 用户:查看全部 用户:编辑 用户:xyz

角色用户: 用户:editOwn 用户:viewOwn 用户:等

如果可能,然后在项目中使用[Authorize(Policy = "users:kvm")] 标签。

但是,我找不到任何有关如何从 Auth0 实际使用授权扩展的资源。我完全不知所措,所以如果有人能指导我在哪里寻找这些,我会很高兴。

【问题讨论】:

【参考方案1】:

您可以使用 Authorization Extension 创建代表对每个应用程序的访问权限的权限。

注意:创建权限时“名称”应反映应用程序的客户端 ID

下面的示例图片

然后创建代表每个应用程序的角色并确保选择了相关权限。

在本例中:角色名称为“SampleClientAccess”

    然后创建组并链接您创建的角色。将相关用户添加到群组

    最后一步。转到仪表板 > 规则 > 创建自定义规则和以下代码。

function (user, context, callback)  
      // Assume that permission for an application is the client_id of the permission then
 
     if (user.permissions.indexOf(context.clientID) === -1 )
         callback(new UnauthorizedError('You are not allowed to access ' + context.clientName + JSON.stringify(user)));
     
     callback(null, user, context);

希望这会对您有所帮助。

【讨论】:

不完全是我想要的。我的想法是,在 Auth0 授权扩展中设置权限,例如:editOtherAccount - 然后在我的应用程序中执行:If(LoggedIn.HasPermission("editOtherAccount")) 等。现在的主要问题是用户必须注销,然后在更新权限之前重新登录,所以如果我对用户进行降级,它不会立即影响他们【参考方案2】:

授权扩展可通过API访问

您必须启用 API 访问并设置机器对机器的通信,以便您可以访问端点。 (如链接中所述)

然后使用this文档来管理权限、角色、组等。

每个请求都必须包含一个令牌 (JWT),您必须事先通过 POST 请求从 https://yourdomain.auth0.com/oauth/token 获取该令牌。

你必须提供四个参数:

grant_type = client_credentials 
client_id = from your auth0 application
client_secret = from your auth0 application
audience=urn:auth0-authz-api

将令牌作为"Authorization" : "Bearer #YOURTOKEN#"放入每个请求的标头中

您可以使用任何 REST 客户端来访问端点。首先,我建议Postman 测试端点并检查您需要哪些调用。有一个方便的collection,您可以通过一些调整来使用。

【讨论】:

【参考方案3】:

我决定放弃 auth0 的授权并自己制定一个系统。

无法理解文档。

【讨论】:

【参考方案4】:

我想添加我在旧版 .NET MVC 应用程序和 .NET Core 2.0 API 中的使用方式,因为我希望它可以为我节省大量时间来解决这个问题。

如果您想要的只是在 auth0 中获取组、权限、角色和更新用户帐户,请按照@StV 的答案中的步骤操作。

但是,如果您想在 .NET 中检查权限/角色等,那么我就是这样做的:

将组、角色和权限添加到访问或 Id 令牌(或两者)。要做到这一点,请按照说明here

一旦您从上述配置步骤发布规则,您必须自己在 Auth0 中创建另一个规则,以将信息复制到令牌中(这让我有一段时间)。这必须在 Auth0 发布/创建的规则之后运行。我的看起来像这样:

function (user, context, callback) 
  if(user.app_metadata) 
    var namespace = 'https://visionplatform.com/';
    context.accessToken[namespace + 'roles'] = user.roles;
    context.accessToken[namespace + 'permissions'] = user.permissions;
    context.idToken[namespace + 'roles'] = user.roles;
    context.idToken[namespace + 'permissions'] = user.permissions;    
  
  callback(null, user, context);

现在,如果您的用户登录,他们将在其令牌中拥有自己的组、角色和权限。但是请记住,您通过身份验证的特定客户端的组、角色和权限会显示(我为此浪费了几个小时)。

所以现在您可以在解码 JWT 的代码中获取/检查权限。这是我在库方法中如何完成此操作的一些 sn-ps 代码(即不是授权属性):

首先获取您的 TokenValidationPrams

public TokenValidationParameters GetTokenValidationParameter(string domain, string audience)

    IConfigurationManager<OpenIdConnectConfiguration> configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>($"domain.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
    var openIdConfig = AsyncHelper.RunSync(async () => await configurationManager.GetConfigurationAsync(CancellationToken.None));

    return new TokenValidationParameters
    
        ValidIssuer = $"domain",
        ValidAudiences = new[]  audience ,
        IssuerSigningKeys = openIdConfig.SigningKeys
    ;

然后解码您的 JWT 以获取声明

private ClaimsPrincipal GetValidatedToken(string token, TokenValidationParameters validationParameters)

    var handler = new JwtSecurityTokenHandler();
    return handler.ValidateToken(token, validationParameters, out var _);

现在您可以检查声明原则以查看它是否包括您的组、权限或其他内容(请注意,我只是检查权限)。

public bool ValidateTokenClaimsPermissionExists(string token, string domain, string audience, string permission)

    var claimsPrincipal = GetValidatedToken(token, _tokenValidationParameters);

    var scopePermission = claimsPrincipal.FindFirst(c => c.Type == Constants.PermissionsClaimTypeName && c.Value == permission);
    return scopePermission != null;

我使用上面的方法进行单独的调用来检查权限,但是您可以(并且可能应该)编写自己的授权属性,或者如果您使用 .NET Core,您可以编写一个 AuthorizationHandler 中间件来检查您想要的任何声明文档here。下面的一个检查范围,但您可以根据上面的代码对其进行调整以检查权限:

protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasScopeRequirement requirement)

    // If user does not have the scope claim, get out of here
    if (!context.User.HasClaim(c => c.Type == "scope" && c.Issuer == requirement.Issuer))
    
        return Task.CompletedTask;
    

    // Split the scopes string into an array
    var scopes = context.User.FindFirst(c => c.Type == "scope" && c.Issuer == requirement.Issuer).Value.Split(' ');

    // Succeed if the scope array contains the required scope
    if (scopes.Any(s => s == requirement.Scope))
        context.Succeed(requirement);

    return Task.CompletedTask;

我也将使用上述所有内容为我的 .NET MVC 应用程序编写授权属性。

【讨论】:

【参考方案5】:

对于简单的设置,您可以通过 Auth0 GUI 设置角色并使用规则将其应用于用户:

function (user, context, callback) 

   // Roles should only be set to verified users.
  if (!user.email || !user.email_verified) 
    return callback(null, user, context);
  

  user.app_metadata = user.app_metadata || ;

  const assignedRoles = (context.authorization || ).roles;

  const addRolesToUser = function(user) 
    return assignedRoles;
  ;

  const roles = addRolesToUser(user);

  user.app_metadata.roles = roles;
  auth0.users.updateAppMetadata(user.user_id, user.app_metadata)
    .then(function() 
      context.idToken['https://schemas.<yourdomain>.com'] = user.app_metadata.roles;
      callback(null, user, context);
    )
    .catch(function (err) 
      callback(err);
    );

你的 startup.cs 应该是这样的:

services.AddAuthorization(options =>

  options.AddPolicy("Administrator", authBuilder =>  authBuilder.RequireRole("Administrator"); );
  options.AddPolicy("User", authBuilder =>  authBuilder.RequireRole("Administrator", "User"); );

以控制器为例:

[Authorize(Roles = "Administrator, User")]
<<your code>>

【讨论】:

以上是关于Auth0,带有授权扩展和 ASP.NET 授权的主要内容,如果未能解决你的问题,请参考以下文章

通过 Auth0 React 和 ASP.net 核心授权然后使用 JWT 令牌

Asp.Net Core 中的多个 JWT 授权机构/发行人

带有自定义登录页面的 Auth0 授权代码流

ASP.NET Core - AddJwtBearer - 授权 URL,它是如何工作的?

ASP.NET Core 3.1 中基于角色的授权,带有 Identity 和 ExternalLogin

ASP.NET Core MVC 授权的扩展:自定义 Authorize Attribute 和 IApplicationModelProvide