public async Task <JwtRefreshDTO> AllowLogin(string username, string password) { var helperShared = new YetAnotherPrivateChat.Shared.HelperShared.Helper(); var user = await ctx.Users.FirstOrDefaultAsync(c => c.Username == username); var allowed = helperShared.ComparePassword(user.Password, password); if (!allowed) { throw new Exception("Denied login, please check your password and username"); } int expiration = 6; /* * What is the rationale of adding the row id to the Refresh token? * Since we need to check if the Refresh Token is still valid or not we need some identification. * I could send a blank Refresh token and save its string to the DB, but them I would have all of the Refresh tokens stored * If a breach happened the attacker would have access of all the users, but now since I'm not storing anything the attacker would also need the secret key * So I'm pretty much adding another chain to protect the application. */ var refreshTokenDb = new RefreshTokenDb(user.UserId, expiration); var result = _context.RefreshDb.Add(refreshTokenDb); await _context.SaveChangesAsync(); var refreshToken = new RefreshToken(expiration, result.Entity.RefreshTokenDbId); var jwt = new JwtToken(user.UserId, user.RegistrationDate, user.Admin); return(new JwtRefreshDTO(refreshToken, jwt)); }
public static RefreshToken Map(this RefreshTokenDb refreshToken) { if (refreshToken is null) { return(null); } return(new() { Id = refreshToken.Id, Token = refreshToken.Token, Expires = refreshToken.Expires, Created = refreshToken.Created, CreatedByIp = refreshToken.CreatedByIp, Revoked = refreshToken.Revoked, RevokedByIp = refreshToken.RevokedByIp, ReplacedByToken = refreshToken.ReplacedByToken, ReasonRevoked = refreshToken.ReasonRevoked }); }
public async Task <RefreshToken> RefreshRefreshToken(int userId, int tokenId) { /* * If the Refresh token is already older than one month, a new one is created. * Why? I think is a good idea to rotate those keys. * Why one month? IDK, probably should be less than one month, just trying to avoid some DB trip. * Keep in mind that the token is still valid for 6 month, by default, so no problem if the user logs before one month. * Older Refresh Token became invalid. */ int expiration = 6; var refreshTokenDb = new RefreshTokenDb(userId, expiration); var result = _context.RefreshDb.Add(refreshTokenDb); await _context.SaveChangesAsync(); var refreshToken = new RefreshToken(expiration, result.Entity.RefreshTokenDbId); await DisableRefreshToken(tokenId); return(refreshToken); }
private async Task <AuthenticationResult> GenerateAuthenticationResult(IdentityUser newUser) { var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.ASCII.GetBytes(_jwtSettings.Secret); var claims = new List <Claim> { new Claim(JwtRegisteredClaimNames.Sub, newUser.Email), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new Claim(JwtRegisteredClaimNames.Email, newUser.Email), new Claim("id", newUser.Id) }; var userClaims = await _userManager.GetClaimsAsync(newUser); claims.AddRange(userClaims); var userRoles = await _userManager.GetRolesAsync(newUser); foreach (var userRole in userRoles) { claims.Add(new Claim(ClaimTypes.Role, userRole)); var role = await _userManager.FindByNameAsync(userRole); if (role == null) { continue; } var roleClaims = await _userManager.GetClaimsAsync(role); foreach (var roleClaim in roleClaims) { if (claims.Contains(roleClaim)) { continue; } claims.Add(roleClaim); } } var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(claims), Expires = DateTime.Now.Add(_jwtSettings.TokenLifeTime), SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) }; var token = tokenHandler.CreateToken(tokenDescriptor); var refreshToken = new RefreshTokenDb { JwtId = token.Id, UserId = newUser.Id, CreationDate = DateTime.UtcNow, ExpiryDate = DateTime.UtcNow.AddDays(30) }; await _dbContext.RefreshTokens.AddAsync(refreshToken); await _dbContext.SaveChangesAsync(); return(new AuthenticationResult { Success = true, Token = tokenHandler.WriteToken(token), RefreshToken = refreshToken.Token }); }