Example #1
0
        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);
        }
Example #2
0
        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");
            }
        }
Example #3
0
        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
            }
                );
        }