【问题标题】:How to use auto generated refresh token in asp.net core 3.1?如何在 asp.net core 3.1 中使用自动生成的刷新令牌?
【发布时间】:2020-09-21 20:51:18
【问题描述】:

在我的 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 的任何示例。

【问题讨论】:

    标签: c# security asp.net-core jwt


    【解决方案1】:

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

    以下是标准通信流程specified OAuth2 RFC 6749 documentation,它解释了使用刷新令牌的场景。

    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) 授权服务器对客户端进行身份验证并验证 刷新令牌,如果有效,则发出一个新的访问令牌(并且, (可选)一个新的刷新令牌)。

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

    【讨论】:

      猜你喜欢
      • 2019-10-15
      • 2018-05-12
      • 2020-05-22
      • 2021-10-30
      • 2019-10-01
      • 2019-03-08
      • 2018-03-30
      • 2020-07-06
      • 1970-01-01
      相关资源
      最近更新 更多