如何使用基于策略的授权将所需的声明附加到令牌?

Posted

技术标签:

【中文标题】如何使用基于策略的授权将所需的声明附加到令牌?【英文标题】:How to attach needed claims to tokens with policy-based authorization? 【发布时间】:2021-09-18 14:48:57 【问题描述】:

我正在尝试在我的 Web API 中实现基于策略的授权。我想弄清楚的是如何确定在为用户的登录操作生成令牌时应将哪些声明添加到令牌中。我应该在数据库中存储每个用户的索赔信息,还是我误解了一些概念?

这是我用来生成 JWT/refresh-token 对的方法:

public async Task<AuthenticationResponse> GenerateTokenPairForUserAsync(User user)

    var jwtTokenHandler = new JwtSecurityTokenHandler();
    var key = Encoding.ASCII.GetBytes(_jwtConfig.Secret);
    var guid = Guid.NewGuid().ToString();
    var tokenDescriptor = new SecurityTokenDescriptor
    
        Subject = new ClaimsIdentity(new[]
        
            new Claim(JwtRegisteredClaimNames.Sub, user.Email),
            new Claim(ClaimTypes.Sid, user.Id.ToString()),
            new Claim(JwtRegisteredClaimNames.Email, user.Email),
            new Claim(ClaimTypes.Role, user.RoleId.ToString()),
            new Claim(JwtRegisteredClaimNames.Jti, guid)
        ),
        Expires = DateTime.UtcNow.Add(_jwtConfig.TokenLifetime),
        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature)
    ;

    var token = jwtTokenHandler.CreateToken(tokenDescriptor);
    var jwtToken = jwtTokenHandler.WriteToken(token);

    var refreshToken = new RefreshToken
    
        JwtId = token.Id,
        IsUsed = false,
        IsRevoked = false,
        UserId = user.Id,
        CreationDate = DateTime.UtcNow,
        ExpiryDate = DateTime.UtcNow.Add(_refreshTokenConfig.TokenLifetime),
        Token = RandomString(25) + Guid.NewGuid()
    ;

    await _refreshTokenRepository.CreateAsync(refreshToken);

    return new AuthenticationResponse
    
        Token = jwtToken,
        Success = true,
        RefreshToken = refreshToken.Token
    ;

【问题讨论】:

【参考方案1】:

你需要做一些事情来实现:

您应该了解哪些客户可以接收哪些声明。客户端,即调用您的授权端点的应用程序。如果你只有一个,那么这不是问题,但如果你有很多,你应该在数据库的某个地方保存一个列表,列出给定客户端应该在令牌中收到的所有声明。

将范围映射到声明很方便。然后,在授权请求中,您可以请求范围,本质上是声明组。如果您的客户(或客户)实际上可以请求具有不同范围的令牌,您将需要它。例如。您可能想要请求一个可用于执行一些更敏感操作的令牌,例如更改用户的电子邮件。然后,您可以要求服务器发出令牌,其范围可能为“admin”,其中包括声明can_change_email: true。然后可以使用此声明来执行授权决策。

最后,您需要知道,对于每项索赔,数据的来源是什么。因此,一旦您知道您的令牌必须包含声明 claim1claim2claim3,那么您就必须知道从哪里获取数据。这可以是硬编码的 - 例如你实现了一个getValueForClaim2() 方法,它知道它应该从数据库中读取数据(例如,它是用户的电话号码)。或者您可以创建一些更复杂的解决方案,在其中保留一些到 claimProviders 的映射,然后实现这些提供程序。最后,您从哪里获取数据完全取决于您 - 这可以是数据库、文件、可能是 API 调用,或者是根据某些输入计算的值。

如果您想了解有关此主题的更多信息,请查看有关我们在 Curity 撰写的声明的这些资源:https://curity.io/resources/claims/。

【讨论】:

以上是关于如何使用基于策略的授权将所需的声明附加到令牌?的主要内容,如果未能解决你的问题,请参考以下文章

如何设置 Visual Studio 以将所需的 DLL 文件复制到发布版本中的发布目录中?

如何正确地将所需的 HTML 属性设置为 TymeLeaf 页面的输入标记?

如何将所需的参数传递给 Powershell ISE 中的脚本?

如何使用自定义策略模式实现 jwt 令牌基础身份验证以在 .net 核心中进行授权?

如何获取 hideSoftInputFromInputMethod(token, flags) 所需的令牌?

如何在 Flask 中实现登录所需的装饰器