如何使用基于策略的授权将所需的声明附加到令牌?
How to attach needed claims to tokens with policy-based authorization?
我正在尝试在我的 Web API 中实施基于策略的授权。我想弄清楚的是如何确定在 his/her 登录操作时为用户生成令牌时应将哪些声明添加到令牌中。我应该在数据库中存储关于每个用户的索赔信息,还是我误解了一些概念?
这是我用来生成 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
};
}
你需要做一些事情来实现:
您应该具有哪些客户端可以接收哪些声明的映射。客户端,即调用您的授权端点的应用程序。如果你只有一个,那么这不是问题,但如果你有很多,你应该在数据库的某个地方保留一个列表,列出给定客户端应该在令牌中接收的所有声明。
将范围映射到声明很方便。然后,在授权请求中,您可以请求范围,这些范围本质上是声明组。如果您的客户(或客户)实际上可以请求具有不同范围的令牌,您将需要它。例如。您可能想要请求一个令牌,该令牌可用于执行一些更敏感的操作,例如更改用户的电子邮件。然后,您可以要求服务器颁发范围可能为“admin”的令牌,这转化为声明 can_change_email: true
等。此声明随后可用于执行授权决策。
最后,您需要了解每项索赔的数据来源。因此,一旦您知道您的令牌必须包含声明 claim1
、claim2
和 claim3
,那么您必须知道从哪里获取数据。这可以是硬编码的——例如您实现了一个 getValueForClaim2()
方法,该方法知道它应该从数据库中读取数据(例如,它是用户的 phone 号码)。或者您可以创建一些更复杂的解决方案,在其中保留一些到 claimProviders 的映射,然后实现这些提供程序。最后,您从哪里获取数据完全取决于您 - 这可以是数据库、文件,也许是 API 调用,或者根据某些输入计算值。
查看这些关于我们在 Curity 撰写的声明的资源:https://curity.io/resources/claims/ 如果您想了解有关此主题的更多信息。
我正在尝试在我的 Web API 中实施基于策略的授权。我想弄清楚的是如何确定在 his/her 登录操作时为用户生成令牌时应将哪些声明添加到令牌中。我应该在数据库中存储关于每个用户的索赔信息,还是我误解了一些概念?
这是我用来生成 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
};
}
你需要做一些事情来实现:
您应该具有哪些客户端可以接收哪些声明的映射。客户端,即调用您的授权端点的应用程序。如果你只有一个,那么这不是问题,但如果你有很多,你应该在数据库的某个地方保留一个列表,列出给定客户端应该在令牌中接收的所有声明。
将范围映射到声明很方便。然后,在授权请求中,您可以请求范围,这些范围本质上是声明组。如果您的客户(或客户)实际上可以请求具有不同范围的令牌,您将需要它。例如。您可能想要请求一个令牌,该令牌可用于执行一些更敏感的操作,例如更改用户的电子邮件。然后,您可以要求服务器颁发范围可能为“admin”的令牌,这转化为声明
can_change_email: true
等。此声明随后可用于执行授权决策。最后,您需要了解每项索赔的数据来源。因此,一旦您知道您的令牌必须包含声明
claim1
、claim2
和claim3
,那么您必须知道从哪里获取数据。这可以是硬编码的——例如您实现了一个getValueForClaim2()
方法,该方法知道它应该从数据库中读取数据(例如,它是用户的 phone 号码)。或者您可以创建一些更复杂的解决方案,在其中保留一些到 claimProviders 的映射,然后实现这些提供程序。最后,您从哪里获取数据完全取决于您 - 这可以是数据库、文件,也许是 API 调用,或者根据某些输入计算值。
查看这些关于我们在 Curity 撰写的声明的资源:https://curity.io/resources/claims/ 如果您想了解有关此主题的更多信息。