|
|
|
@@ -103,10 +103,10 @@ namespace Diligent.WebAPI.Business.Services |
|
|
|
var tokenDescriptor = new SecurityTokenDescriptor |
|
|
|
{ |
|
|
|
Subject = new ClaimsIdentity(new[] { |
|
|
|
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), |
|
|
|
new Claim(JwtRegisteredClaimNames.Jti, user.Id.ToString()), |
|
|
|
new Claim("id", user.Id.ToString()) |
|
|
|
}), |
|
|
|
Expires = DateTime.UtcNow.AddMinutes(_authSettings.JwtExpiredTime), |
|
|
|
Expires = DateTime.UtcNow.AddSeconds(_authSettings.JwtExpiredTime), |
|
|
|
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) |
|
|
|
}; |
|
|
|
var token = tokenHandler.CreateToken(tokenDescriptor); |
|
|
|
@@ -116,7 +116,7 @@ namespace Diligent.WebAPI.Business.Services |
|
|
|
var refreshToken = new RefreshToken |
|
|
|
{ |
|
|
|
Token = writedToken, |
|
|
|
JwtId = token.Id, |
|
|
|
JwtId = user.Id.ToString(), |
|
|
|
UserId = user.Id, |
|
|
|
User = user, |
|
|
|
CreationDate = DateTime.UtcNow, |
|
|
|
@@ -160,23 +160,43 @@ namespace Diligent.WebAPI.Business.Services |
|
|
|
return new RefreshTokenResultDto { Error = "Invalid token" }; |
|
|
|
} |
|
|
|
|
|
|
|
var expiryDateUnix = long.Parse(validatedToken.Claims.Single(x => x.Type == JwtRegisteredClaimNames.Exp).Value); |
|
|
|
var jti = validatedToken.Claims.Single(x => x.Type == JwtRegisteredClaimNames.Jti).Value; |
|
|
|
|
|
|
|
var expiryDateTimeUtc = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) |
|
|
|
.AddSeconds(expiryDateUnix); |
|
|
|
var storedRefreshToken = await _databaseContext.RefreshTokens.SingleOrDefaultAsync(x => x.JwtId == jti); |
|
|
|
|
|
|
|
if (expiryDateTimeUtc > DateTime.UtcNow) |
|
|
|
if (storedRefreshToken == null) |
|
|
|
{ |
|
|
|
return new RefreshTokenResultDto { Error = "This token hasn't expired yet" }; |
|
|
|
return new RefreshTokenResultDto { Error = "This refresh token does not exist" }; |
|
|
|
} |
|
|
|
|
|
|
|
var jti = validatedToken.Claims.Single(x => x.Type == JwtRegisteredClaimNames.Jti).Value; |
|
|
|
var userk = await _databaseContext.Users.Where(u => u.Id == storedRefreshToken.UserId).FirstOrDefaultAsync(); |
|
|
|
|
|
|
|
var storedRefreshToken = await _databaseContext.RefreshTokens.SingleOrDefaultAsync(x => x.Token == model.RefreshToken); |
|
|
|
if(userk == null) |
|
|
|
{ |
|
|
|
return new RefreshTokenResultDto { Error = "There is no user which is associated with refresh token" }; |
|
|
|
} |
|
|
|
|
|
|
|
if (storedRefreshToken == null) |
|
|
|
var expiryDateUnix = long.Parse(validatedToken.Claims.Single(x => x.Type == JwtRegisteredClaimNames.Exp).Value); |
|
|
|
|
|
|
|
var expiryDateTimeUtc = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) |
|
|
|
.AddMinutes(expiryDateUnix); |
|
|
|
|
|
|
|
if (expiryDateTimeUtc < DateTime.UtcNow) |
|
|
|
{ |
|
|
|
return new RefreshTokenResultDto { Error = "This refresh token does not exist" }; |
|
|
|
storedRefreshToken.ExpiryDate = DateTime.UtcNow.AddMinutes(_authSettings.JwtRefreshExpiredTime); |
|
|
|
await _databaseContext.SaveChangesAsync(); |
|
|
|
return new RefreshTokenResultDto |
|
|
|
{ |
|
|
|
Data = new AuthenticateResponseDto |
|
|
|
{ |
|
|
|
Id = userk.Id, |
|
|
|
FirstName = userk.FirstName, |
|
|
|
LastName = userk.LastName, |
|
|
|
Username = userk.UserName, |
|
|
|
Token = model.Token, |
|
|
|
RefreshToken = model.RefreshToken |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
if (DateTime.UtcNow > storedRefreshToken.ExpiryDate) |
|
|
|
@@ -189,18 +209,13 @@ namespace Diligent.WebAPI.Business.Services |
|
|
|
return new RefreshTokenResultDto { Error = "This refresh token has been invalidated" }; |
|
|
|
} |
|
|
|
|
|
|
|
if (storedRefreshToken.Used) |
|
|
|
{ |
|
|
|
return new RefreshTokenResultDto { Error = "This refresh token has been used" }; |
|
|
|
} |
|
|
|
|
|
|
|
if (storedRefreshToken.JwtId != jti) |
|
|
|
{ |
|
|
|
return new RefreshTokenResultDto { Error = "This refresh token does not match this JWT" }; |
|
|
|
} |
|
|
|
|
|
|
|
storedRefreshToken.Used = true; |
|
|
|
_databaseContext.RefreshTokens.Update(storedRefreshToken); |
|
|
|
storedRefreshToken.ExpiryDate = DateTime.UtcNow.AddMinutes(_authSettings.JwtRefreshExpiredTime); |
|
|
|
|
|
|
|
await _databaseContext.SaveChangesAsync(); |
|
|
|
|
|
|
|
var user = await _userManager.FindByIdAsync(validatedToken.Claims.Single(x => x.Type == "id").Value); |
|
|
|
@@ -209,11 +224,19 @@ namespace Diligent.WebAPI.Business.Services |
|
|
|
|
|
|
|
return new RefreshTokenResultDto |
|
|
|
{ |
|
|
|
Token = token |
|
|
|
Data = new AuthenticateResponseDto |
|
|
|
{ |
|
|
|
Id = userk.Id, |
|
|
|
FirstName = userk.FirstName, |
|
|
|
LastName = userk.LastName, |
|
|
|
Username = userk.UserName, |
|
|
|
Token = model.Token, |
|
|
|
RefreshToken = model.RefreshToken |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
private ClaimsPrincipal GetPrincipalFromToken(string token) |
|
|
|
private ClaimsPrincipal? GetPrincipalFromToken(string token) |
|
|
|
{ |
|
|
|
var tokenHandler = new JwtSecurityTokenHandler(); |
|
|
|
|
|
|
|
@@ -240,13 +263,13 @@ namespace Diligent.WebAPI.Business.Services |
|
|
|
|
|
|
|
return principal; |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
catch (Exception) |
|
|
|
{ |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private bool IsJwtWithValidSecurityAlgorithm(SecurityToken validatedToken) |
|
|
|
private static bool IsJwtWithValidSecurityAlgorithm(SecurityToken validatedToken) |
|
|
|
{ |
|
|
|
return (validatedToken is JwtSecurityToken jwtSecurityToken) && |
|
|
|
jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, |