简体   繁体   English

如何在asp.net core web api中实现JWT Refresh Tokens(没有第三方)?

[英]How to implement JWT Refresh Tokens in asp.net core web api (no 3rd party)?

I'm in the process of implementing a web api using asp.net core that is using JWT. 我正在使用使用JWT的asp.net核心实现web api。 I am not using a third party solution such as IdentityServer4 as I am trying to learn. 我正在尝试学习,我没有使用像IdentityServer4这样的第三方解决方案。

I've gotten the JWT configuration to work, but am stumped on how to implement refresh tokens for when the JWT's expire. 我已经让JWT配置工作了,但我很难知道如何在JWT到期时实现刷新令牌。

Below is some sample code in my Configure method inside startup.cs. 下面是startup.cs中我的Configure方法中的一些示例代码。

app.UseJwtBearerAuthentication(new JwtBearerOptions()
{
    AuthenticationScheme = "Jwt",
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,
    TokenValidationParameters = new TokenValidationParameters()
    {
        ValidAudience = Configuration["Tokens:Audience"],
        ValidIssuer = Configuration["Tokens:Issuer"],
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"])),
        ValidateLifetime = true,
        ClockSkew = TimeSpan.Zero
    }
});

Below is the Controller method used to generate the JWT. 下面是用于生成JWT的Controller方法。 I have set expiration to 30 seconds for testing purposes. 为测试目的,我将到期时间设置为30秒。

    [Route("Token")]
    [HttpPost]
    public async Task<IActionResult> CreateToken([FromBody] CredentialViewModel model)
    {
        try
        {
            var user = await _userManager.FindByNameAsync(model.Username);

            if (user != null)
            {
                if (_hasher.VerifyHashedPassword(user, user.PasswordHash, model.Password) == PasswordVerificationResult.Success)
                {
                    var userClaims = await _userManager.GetClaimsAsync(user);

                    var claims = new[]
                    {
                        new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
                        new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
                    }.Union(userClaims);

                    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwt.Key));
                    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

                    var token = new JwtSecurityToken(
                            issuer: _jwt.Issuer,
                            audience: _jwt.Audience,
                            claims: claims,
                            expires: DateTime.UtcNow.AddSeconds(30),
                            signingCredentials: creds
                        );

                    return Ok(new
                    {
                        access_token = new JwtSecurityTokenHandler().WriteToken(token),
                        expiration = token.ValidTo
                    });
                }
            }
        }
        catch (Exception)
        {

        }

        return BadRequest("Failed to generate token.");
    }

Would be very grateful for some guidance. 非常感谢一些指导。

First of all, you need to generate a refresh token and persist it somewhere. 首先,您需要生成一个刷新令牌并将其保留在某处。 This is because you want to be able to invalidate it if needed. 这是因为您希望能够在需要时使其无效。 If you were to follow the same pattern as an access token - where all the data is contained within the token - a token that ends up in the wrong hands can the be used to generate new access tokens for the lifetime of the refresh token, which can be a really long time. 如果您遵循与访问令牌相同的模式 - 其中所有数据都包含在令牌中 - 最终落入坏人手中的令牌可用于在刷新令牌的生命周期内生成新的访问令牌,可能很长一段时间。

So what the heck do you need to persist? 那么你需要坚持到底是什么?

You need a unique identifier of some sort that's not easy guessable, a GUID will do just fine. 你需要一种不容易猜到的某种唯一标识符,一个GUID就可以了。 You also need the data to be able to issue a new access token, most likely a username. 您还需要数据能够发出新的访问令牌,很可能是用户名。 Having a username you can then skip the VerifyHashedPassword(...)-part but for the rest of it, just follow the same logic. 拥有用户名后,您可以跳过VerifyHashedPassword(...) - 部分但是对于其余部分,只需遵循相同的逻辑。

To obtain a refresh token, you normally use the scope "offline_access", this being something that you provide in your model (CredentialViewModel) when making a token request. 要获取刷新令牌,通常使用范围“offline_access”,这是您在发出令牌请求时在模型(CredentialViewModel)中提供的内容。 Unlike a normal access token request, you don't need to provide your username and password, but instead the refresh token. 与普通访问令牌请求不同,您不需要提供用户名和密码,而是提供刷新令牌。 When getting a request with a refresh token, you lookup the persisted identifier and issue a token for the user found. 使用刷新令牌获取请求时,您将查找持久标识符并为找到的用户发出令牌。

Following is pseudo code for the happy path: 以下是快乐路径的伪代码:

[Route("Token")]
[HttpPost]
public async Task<IActionResult> CreateToken([FromBody] CredentialViewModel model)
{
    if (model.GrantType is "refresh_token")
    {
        // Lookup which user is tied to model.RefreshToken
        // Generate access token from the username (no password check required)
        // Return the token (access + expiration)
    }
    else if (model.GrantType is "password")
    {
        if (model.Scopes contains "offline_access")
        {
            // Generate access token
            // Generate refresh token (random GUID + model.username)
            // Persist refresh token
            // Return the complete token (access + refresh + expiration)
        }
        else
        {
            // Generate access token
            // Return the token (access + expiration)
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 ASP.NET 核心 Web API - 如何使用第 3 方 API 基于条件 - ASP.NET Core Web API - How to Consume 3rd party API Based on Condition ASP.NET Core Web API - 如何使用 HttpClient 使用 3rd 方 API - ASP.NET Core Web API - How to Consume 3rd party API using HttpClient 如何在第三方ASP.NET Web API客户端中使用Oauth生成的令牌? - How to use an Oauth Generated Token in a 3rd party asp.net web API client? 我如何验证第三方用户访问我的Web API asp.net? - how do i authenticate 3rd party user to access my web API asp.net? 调用第 3 方 API asp .net 核心 - Calling 3rd party API asp .net Core 如何在不等待 ASP.NET API 中的响应的情况下处理多个 3rd 方 API - How to process multiple 3rd party APIs without waiting for their response in ASP.NET API 使用Microsoft Graph令牌通过Jwt Bearer令牌保护ASP.NET Core Web API - Using Microsoft Graph token to secure ASP.NET Core Web API with Jwt Bearer tokens ASP.NET 核心 API 使用 JWT 不记名令牌进行身份验证 - ASP.NET Core API authenticate using JWT bearer tokens ASP.NET Core:Docker 还原/构建未能包含项目中的第 3 方程序集 - ASP.NET Core: Docker restore/build failed to include the 3rd party assembly from project 在ASP.NET MVC中管理对第三方应用程序的共享API调用的最佳场所 - Best Place to manage shared API calls to 3rd party application inside my asp.net mvc
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM