如何在核心 3.1 中使用自动生成 asp.net 刷新令牌?



在我的aspnet Core 3.1项目中,我正在使用CQRS模式和JWT身份验证,我想 在令牌过期时实现自动刷新令牌,并非每次用户都要求输入用户名和密码,我也不想将刷新令牌存储在数据库中。刷新令牌的最佳方法是什么。

我的 jwtgenerator 类用于令牌和刷新令牌。

public class JwtGenerator : IJwtGenerator
{
private readonly SymmetricSecurityKey _key;
public JwtGenerator(IConfiguration config)
{
_key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config.GetSection("AppSettings:Token").Value));
}
public string GenerateToken(int size=32)
{
var randomNumber = new byte[size];
using var rng = RandomNumberGenerator.Create();
rng.GetBytes(randomNumber);
return Convert.ToBase64String(randomNumber);
}
public string CreateToken(User user)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, user.UserName),
new Claim(ClaimTypes.Role, user.Role.ToString("G").ToLower())
};
var creds = new SigningCredentials(_key, SecurityAlgorithms.HmacSha512Signature);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.Now.AddDays(1),
SigningCredentials = creds
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
}

我的登录方法如下所示:

public async Task<GetToken> Handle(Query request, CancellationToken 
cancellationToken)
{
var user = await _userManager.FindByNameAsync(request.Username);
if (user == null)
throw new UnauhtorizedException("Unauthorized");
var result = await _signInManager.CheckPasswordSignInAsync(user, request.Password,false);
if (result.Succeeded)
{
return new GetToken()
{
Token = _jwtGenerator.CreateToken(user),
RefreshToken = _jwtGenerator.GenerateToken(32)
};
}
throw new UnauhtorizedException("Unauthorized");
}

我的配置jwt和身份验证启动:

var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetSection("AppSettings:Token").Value));
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(opt =>
{
opt.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = key,
ValidateAudience = false,
ValidateIssuer = false
};
});

登录后,我得到正确的结果:

{
"token": "mytoken",
"refreshToken": "tha1qH7PTx4PNoVeD7D7h/BmEZfdS42zWxriexePWlg="
}

附言我没有找到 CQRS 的任何示例。

你在那里做的事情在OAuth2中被称为Resource Owner Password Credential。对我来说,这看起来几乎是一个最小的实现。您需要具有刷新令牌值或至少一个引用值来锚定授权层中的令牌。它不必是数据库来存储这样的值,你可以有内存存储、物理文件或任何你想要的东西。但是无论如何,您都需要保留该值以便稍后进行验证。

下面是标准通信流,指定 OAuth2 RFC 6749 文档,其中介绍了使用刷新令牌的方案。

1.5. 刷新令牌

刷新令牌是用于获取访问令牌的凭据。 刷新 令牌由授权服务器颁发给客户端,并且 用于在当前访问令牌时获取新的访问令牌 变得无效或过期,或获取其他访问令牌 具有相同或更窄的范围(访问令牌可能具有较短的时间 生存期和少于资源授权的权限 所有者(。 颁发刷新令牌是可选的,由 授权服务器。 如果授权服务器发出刷新 令牌,它在颁发访问令牌时包含在内(即步骤 (D( 图1(。

刷新令牌是一个字符串,表示授予 资源所有者的客户端。 字符串通常不透明到 客户端。 令牌表示用于检索授权信息的标识符。 与访问令牌不同,刷新令牌是 仅用于授权服务器,永远不会发送 到资源服务器。

+--------+                                           +---------------+
|        |--(A)------- Authorization Grant --------->|               |
|        |                                           |               |
|        |<-(B)----------- Access Token -------------|               |
|        |               & Refresh Token             |               |
|        |                                           |               |
|        |                            +----------+   |               |
|        |--(C)---- Access Token ---->|          |   |               |
|        |                            |          |   |               |
|        |<-(D)- Protected Resource --| Resource |   | Authorization |
| Client |                            |  Server  |   |     Server    |
|        |--(E)---- Access Token ---->|          |   |               |
|        |                            |          |   |               |
|        |<-(F)- Invalid Token Error -|          |   |               |
|        |                            +----------+   |               |
|        |                                           |               |
|        |--(G)----------- Refresh Token ----------->|               |
|        |                                           |               |
|        |<-(H)----------- Access Token -------------|               |
+--------+           & Optional Refresh Token        +---------------+
Figure 2: Refreshing an Expired Access Token

图 2 所示的流程包括以下步骤:

(A( 客户端通过向 授权服务器并提供授权授权。

(B( 授权服务器对客户端进行身份验证并验证 授权授予,如果有效,则颁发访问令牌 和刷新令牌。

(C( 客户端向资源发出受保护的资源请求 服务器通过提供访问令牌。

(D( 资源服务器验证访问令牌,如果有效, 为请求提供服务。

(E( 重复步骤 (C( 和 (D(,直到访问令牌过期。 如果 客户端知道访问令牌已过期,它会跳到步骤 (G(; 否则,它会发出另一个受保护的资源请求。

(F( 由于访问令牌无效,资源服务器返回 令牌无效错误。

(G( 客户端通过身份验证请求新的访问令牌 授权服务器并显示刷新令牌。 这 客户端身份验证要求基于客户端类型 以及授权服务器策略。

(H( 授权服务器对客户端进行身份验证并验证 刷新令牌,如果有效,则颁发新的访问令牌(并且, (可选(新的刷新令牌(。

此问题是特定于实现的,您可以在应用程序级别实现最佳实践的选项太多。为此,我想说"坚持标准"。

相关内容

  • 没有找到相关文章

最新更新