public async Task <Response> ValidateRefreshTokenAsync(string currentToken, string refreshToken) { var principal = GetClaimsPrincipal(currentToken); if (principal is null || !long.TryParse(GetClaimValue(principal.Claims, ClaimTypes.Expiration), out long expiryDateUnix)) { return(new Response(false, "Invalid token")); } var expiryDatUtc = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) .AddSeconds(expiryDateUnix); if (expiryDatUtc > DateTime.UtcNow) { return(new Response(false, "This token has not expired yet")); } var jti = GetClaimValue(principal.Claims, JwtRegisteredClaimNames.Jti); if (jti is null) { return(new Response(false, "Invalid token")); } var storedRefreshToken = await _refreshTokenRepository.GetRefreshTokensAsync(token => token.Token == refreshToken); if (storedRefreshToken is null) { return(new Response(false, "This refresh token does not exist")); } if (DateTime.UtcNow > storedRefreshToken.ExpiryDate) { return(new Response(false, "This refresh token has expired")); } if (storedRefreshToken.Invalidated) { return(new Response(false, "This refresh token has been invalidated")); } if (storedRefreshToken.Used) { return(new Response(false, "This refresh token has been used")); } if (storedRefreshToken.JwtId != jti) { return(new Response(false, "This refresh does not match this JWT")); } // update status and save in database storedRefreshToken.Used = true; return(new Response(true)); }