public async Task <Guid> SignUpAsync(Dtos.User userDto, string password) { if (string.IsNullOrWhiteSpace(password)) { throw new RegistrationException("Password is required"); } var validator = new Dtos.UserValidator(); ValidationResult result = validator.Validate(userDto); if (!result.IsValid) { string errMess = string.Empty; foreach (var failure in result.Errors) { errMess += $"Property { failure.PropertyName } failed validation. Error was: { failure.ErrorMessage }\n"; } throw new InvalidModelException(errMess); } bool isUserExists = _context.Set <Entities.User>().Include(x => x.UserInfo) .Any(x => x.UserInfo != null && x.UserInfo.Email == userDto.Email); if (isUserExists) { throw new ServiceException(System.Net.HttpStatusCode.Conflict, $"Email \"{userDto.Email}\" is already taken"); } CreatePasswordHash(password, out byte[] passwordHash, out byte[] passwordSalt); var userInfo = new Entities.UserInfo { Id = Guid.NewGuid(), DateOfBirth = userDto.DateOfBirth, Email = userDto.Email, FirstName = userDto.FirstName, FirstNameEng = userDto.FirstNameEng, LastName = userDto.LastName, LastNameEng = userDto.LastNameEng, Patronymic = userDto.Patronymic, PhoneNumber = userDto.PhoneNumber }; await _context.AddAsync(userInfo); var user = new Entities.User { PasswordHash = passwordHash, PasswordSalt = passwordSalt, CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow, Id = Guid.NewGuid(), UserInfo = userInfo }; var role = await _context.Set <Entities.Role>() .FirstOrDefaultAsync(x => x.Name == AppRoles.User); if (role == null) { role = new Entities.Role { Id = Guid.NewGuid(), Name = AppRoles.User, CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }; await _context.Set <Entities.Role>().AddAsync(role); } var userRole = new Entities.UserRoles { RoleId = role.Id, UserId = user.Id }; await _context.Set <Entities.User>().AddAsync(user); await _context.Set <Entities.UserRoles>().AddAsync(userRole); await _context.SaveChangesAsync(); return(user.Id); }
public async Task <Dtos.TokenInfo> RefreshTokenAsync(string refreshToken) { var validationParameters = new TokenValidationParameters { ValidIssuer = _appSettings.Issuer, ValidateIssuer = true, ValidateAudience = true, ValidAudience = _appSettings.Audience, ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_appSettings.Secret)), RequireExpirationTime = true, ValidateLifetime = true }; JwtSecurityToken jwt; try { var claimsPrincipal = new JwtSecurityTokenHandler() .ValidateToken(refreshToken, validationParameters, out var rawValidatedToken); jwt = (JwtSecurityToken)rawValidatedToken; } catch (SecurityTokenValidationException stvex) { throw new ServiceException($"Token failed validation: {stvex.Message}"); } catch (ArgumentException argex) { throw new ServiceException($"Token was invalid: {argex.Message}"); } var refreshTokenIdClaim = jwt.Claims.FirstOrDefault(claim => claim.Type == "rid"); if (refreshTokenIdClaim == null) { throw new InvalidModelException("Invalid token"); } var sessionIdClaim = jwt.Claims.FirstOrDefault(claim => claim.Type == JwtRegisteredClaimNames.Sid); if (sessionIdClaim == null) { throw new InvalidModelException("Invalid token"); } Guid refreshTokenId = Guid.Parse(refreshTokenIdClaim.Value); Guid sessionId = Guid.Parse(sessionIdClaim.Value); Monitor.Enter(syncSessionObj); var hasSession = sessions.Any(s => s.sessionId.Equals(sessionId) && s.refreshTokenId.Equals(refreshTokenId)); if (hasSession) { SessionInfo session = sessions.First(s => s.sessionId.Equals(sessionId) && s.refreshTokenId.Equals(refreshTokenId)); sessions.Remove(session); Monitor.Exit(syncSessionObj); Entities.User user = await _context.Set <Entities.User>() .Include(usr => usr.UserRoles) .ThenInclude(ur => ur.Role) .FirstOrDefaultAsync(usr => usr.Id == session.userId); this.CreateTokens(user, out string newAccessToken, out string newRefreshToken); return(new Dtos.TokenInfo { AccessToken = "Bearer " + newAccessToken, RefreshToken = newRefreshToken, Expire = _appSettings.AccessTokenLifeTime }); } else { Monitor.Exit(syncSessionObj); throw new NotFoundException("Session not found"); } }
private void CreateTokens(Entities.User user, out string accessToken, out string refreshToken) { var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.UTF8.GetBytes(_appSettings.Secret); var claimes = new List <Claim>(); Guid sessionId = Guid.NewGuid(); claimes.Add(new Claim(ClaimTypes.Name, user.Id.ToString())); claimes.Add(new Claim(JwtRegisteredClaimNames.Sid, sessionId.ToString())); foreach (var role in user.UserRoles.ToList()) { claimes.Add(new Claim(ClaimTypes.Role, role.Role.Name)); } var accessTokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(claimes), Expires = DateTime.UtcNow.AddMinutes(_appSettings.AccessTokenLifeTime), SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature), Audience = _appSettings.Audience, Issuer = _appSettings.Issuer }; var acsToken = tokenHandler.CreateToken(accessTokenDescriptor); accessToken = tokenHandler.WriteToken(acsToken); // creating refresh token Guid refreshTId = Guid.NewGuid(); claimes = new List <Claim>(); claimes.Add(new Claim(JwtRegisteredClaimNames.Sid, sessionId.ToString())); claimes.Add(new Claim("rid", refreshTId.ToString())); var refreshTokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(claimes), Expires = DateTime.UtcNow.AddMinutes(_appSettings.RefreshTokenLifeTime), SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature), Audience = _appSettings.Audience, Issuer = _appSettings.Issuer }; var refToken = tokenHandler.CreateToken(refreshTokenDescriptor); refreshToken = tokenHandler.WriteToken(refToken); // register token sessions.Add( new SessionInfo { sessionId = sessionId, expires = DateTime.UtcNow.AddMinutes(_appSettings.RefreshTokenLifeTime), userId = user.Id, refreshTokenId = refreshTId } ); }