1 year ago
#387823
Adam
JWT Refresh Token not working properly when trying refresh after long time?
I am create a JWT access token and refresh token on login of valid user, access token is short lived and refresh token is with expiration time of 7 days, When I am trying to generate new access token after expiry using refresh token it is working fine and response with new access token and refresh token but after long time such as after 3 or 4 hours when I am trying it is not working. I am also comment in Refresh token method code where I am getting error.
Please see my code:
Controller:
public IActionResult RefreshToken([FromBody] RefreshTokenRequest request)
{
try
{
if (string.IsNullOrWhiteSpace(request.RefreshToken))
{
return Unauthorized();
}
var jwtResult = _jwtAuthManager.Refresh(request.RefreshToken, request.AccessToken, DateTime.Now);
var userName = jwtResult.RefreshToken.UserName;
var role = _userService.GetUserRole(userName);
var claims = new[]
{
new Claim(ClaimTypes.Role, role)
};
_logger.LogInformation($"User [{userName}] has refreshed JWT Token");
if (jwtResult == null)
{
return BadRequest();
}
return Ok(new
{
UserName = userName,
Role= role,
AccessToken = jwtResult.AccessToken,
RefreshToken = jwtResult.RefreshToken.TokenString,
Status = "Success",
Message = "New access token generated successfully"
});
}
catch (SecurityTokenException e)
{
return Unauthorized(e.Message); // return 401 so that the client side can redirect the user to login page
}
}
Generate token method:
public JwtAuthResult GenerateTokens(string username, Claim[] claims, DateTime now)
{
var shouldAddAudienceClaim = string.IsNullOrWhiteSpace(claims?.FirstOrDefault(x => x.Type == JwtRegisteredClaimNames.Aud)?.Value);
var jwtToken = new JwtSecurityToken(
_jwtTokenConfig.Issuer,
shouldAddAudienceClaim ? _jwtTokenConfig.Audience : string.Empty,
claims,
expires: now.AddMinutes(_jwtTokenConfig.AccessTokenExpiration),
signingCredentials: new SigningCredentials(new SymmetricSecurityKey(_secret), SecurityAlgorithms.HmacSha256Signature));
var accessToken = new JwtSecurityTokenHandler().WriteToken(jwtToken);
var refreshToken = new RefreshToken
{
UserName = username,
TokenString = GenerateRefreshTokenString(),
ExpireAt = now.AddMinutes(_jwtTokenConfig.RefreshTokenExpiration),
};
_usersRefreshTokens.AddOrUpdate(refreshToken.TokenString, refreshToken, (s, t) => refreshToken);
return new JwtAuthResult
{
AccessToken = accessToken,
RefreshToken = refreshToken
};
}
Refresh Token Method:
public JwtAuthResult Refresh(string refreshToken, string accessToken, DateTime now)
{
var (principal, jwtToken) = DecodeJwtToken(accessToken);
if (jwtToken == null || !jwtToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256Signature))
{
throw new SecurityTokenException("Invalid token");
}
var userName = principal.Identity?.Name;
if (!_usersRefreshTokens.TryGetValue(refreshToken, out var existingRefreshToken))
{
throw new SecurityTokenException("Invalid token not found");
}
var result = existingRefreshToken;
if (existingRefreshToken.UserName != userName || existingRefreshToken.ExpireAt <= now) //After 3 or 4 hours I am getting error in this condition.
{
throw new SecurityTokenException("Invalid UserName or refresh token expired");
}
return GenerateTokens(userName, principal.Claims.ToArray(), now); // need to recover the original claims
}
Claim Principal Method:
public (ClaimsPrincipal, JwtSecurityToken) DecodeJwtToken(string token)
{
if (string.IsNullOrWhiteSpace(token))
{
throw new SecurityTokenException("Invalid token");
}
var principal = new JwtSecurityTokenHandler()
.ValidateToken(token,
new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = _jwtTokenConfig.Issuer,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(_secret),
ValidAudience = _jwtTokenConfig.Audience,
ValidateAudience = true,
ValidateLifetime = false,
ClockSkew = TimeSpan.FromMinutes(1)
},
out var validatedToken);
return (principal, validatedToken as JwtSecurityToken);
}
c#
.net
jwt
refresh-token
0 Answers
Your Answer