private async Task <AuthResult> GenerateJwtToken(IdentityUser user) { var jwtTokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.ASCII.GetBytes(_jwtConfig.Secret); var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new[] { new Claim("Id", user.Id), new Claim(JwtRegisteredClaimNames.Email, user.Email), new Claim(JwtRegisteredClaimNames.Sub, user.Email), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) }), Expires = DateTime.UtcNow.Add(_jwtConfig.), SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) }; var token = jwtTokenHandler.CreateToken(tokenDescriptor); var jwtToken = jwtTokenHandler.WriteToken(token); var refreshToken = new RefreshToken() { JwtID = token.Id, IsUsed = false, UserID = user.Id, AddedDate = DateTime.UtcNow, ExpiryDate = DateTime.Now.AddYears(1), IsRevoked = false, Token = OtherTool.RandomString(25) + Guid.NewGuid() }; await _db.RefreshTokens.AddAsync(refreshToken); await _db.SaveChangesAsync(); return(new AuthResult() { Token = jwtToken, Success = true, RefreshToken = refreshToken.Token }); }
private async Task <AuthResult> VerifyAndGenerateToken(TokenRequest tokenRequest) { var jwtTokenHandler = new JwtSecurityTokenHandler(); try { // Validation 1 - Validation JWT token format var tokenInVerification = jwtTokenHandler.ValidateToken(tokenRequest.Token, _tokenValidationParams, out var validatedToken); // Validation 2 - Validate encryption alg if (validatedToken is JwtSecurityToken jwtSecurityToken) { var result = jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase); if (result == false) { return(null); } } // Validation 3 - validate expiry date var utcExpiryDate = long.Parse(tokenInVerification.Claims.FirstOrDefault(x => x.Type == JwtRegisteredClaimNames.Exp).Value); var expiryDate = OtherTool.UnixTimeStampToDateTime(utcExpiryDate); if (expiryDate > DateTime.UtcNow) { return(new AuthResult() { Success = false, Errors = new List <string>() { "Token has not yet expired" } }); } // validation 4 - validate existence of the token var storedToken = await _db.RefreshTokens.FirstOrDefaultAsync(x => x.Token == tokenRequest.RefreshToken); if (storedToken == null) { return(new AuthResult() { Success = false, Errors = new List <string>() { "Token does not exist" } }); } // Validation 5 - validate if used if (storedToken.IsUsed) { return(new AuthResult() { Success = false, Errors = new List <string>() { "Token has been used" } }); } // Validation 6 - validate if revoked if (storedToken.IsRevoked) { return(new AuthResult() { Success = false, Errors = new List <string>() { "Token has been revoked" } }); } // Validation 7 - validate the id var jti = tokenInVerification.Claims.FirstOrDefault(x => x.Type == JwtRegisteredClaimNames.Jti).Value; if (storedToken.JwtID != jti) { return(new AuthResult() { Success = false, Errors = new List <string>() { "Token doesn't match" } }); } // update current token storedToken.IsUsed = true; _db.RefreshTokens.Update(storedToken); await _db.SaveChangesAsync(); // Generate a new token var dbUser = await _userManager.FindByIdAsync(storedToken.UserID); return(await GenerateJwtToken(dbUser)); } catch (Exception ex) { if (ex.Message.Contains("Lifetime validation failed. The token is expired.")) { return(new AuthResult() { Success = false, Errors = new List <string>() { "Token has expired please re-login" } }); } else { return(new AuthResult() { Success = false, Errors = new List <string>() { "Something went wrong." } }); } } }