예제 #1
0
        private void ValidateRefreshToken(DbRefreshToken refreshToken, ClaimsPrincipal claimsIdentity)
        {
            var jti    = claimsIdentity.Claims.Single(c => c.Type == JwtRegisteredClaimNames.Jti).Value;
            var userId = claimsIdentity.Claims.Single(c => c.Type == "id").Value;

            if (refreshToken is null)
            {
                throw new RefreshTokenNotFoundException();
            }

            if (DateTime.UtcNow > refreshToken.ExpiryDate)
            {
                throw new RefreshTokenExpiredException();
            }

            if (refreshToken.Used)
            {
                throw new InvalidTokenException("This token has already been used.");
            }

            if (refreshToken.JwtId != jti)
            {
                throw new RefreshTokenConflictException();
            }
        }
예제 #2
0
        public async Task <RefreshToken> GetRefreshToken(string token)
        {
            try
            {
                using (var connection = await GetConnectionAsync())
                {
                    var res =
                        await connection.QueryAsync(RegistrarQueries.RefreshTokenSelect, new { Token = token });

                    if (!res.Any())
                    {
                        throw new RecordNotFoundException();
                    }

                    var dbModel = new DbRefreshToken(res.First());
                    return(dbModel.ToModel());
                }
            }
            catch (Exception e)
            {
                if (e is RecordNotFoundException)
                {
                    throw;
                }
                throw new Exception("Could not get Refresh Token");
            }
        }
예제 #3
0
        public IActionResult Refresh([FromQuery] UserTokenRefreshModel userRefreshModel)
        {
            _logger.LogTrace("Update session attempt from {RemoteIp} and {UserAgent} with refresh token {RefreshToken}", UserIp, UserAgent, userRefreshModel.RefreshToken);
            var dbToken = _db.RefreshTokens
                          .Include(rt => rt.NavUser)
                          .FirstOrDefault(rt => rt.Token == userRefreshModel.RefreshToken);

            if (dbToken == null)
            {
                _logger.LogTrace("Invalid refresh token. Need re:login");
                ModelState.AddModelError("RefreshToken", "Invalid refresh token");
                return(BadRequest(new ValidationProblemDetails(ModelState)));
            }

            dbToken.UsedDateTime = _now;
            dbToken.UsedIp       = UserIp;
            var dbUser          = dbToken.NavUser;
            var newRefreshToken = new DbRefreshToken()
            {
                Fingerprint = userRefreshModel.Fingerprint,
                FromTime    = _now,
                ToTime      = _now.AddDays(_authOptions.RefreshTokenLifetimeDays),
                CreatedIp   = UserIp,
                NavUser     = dbUser,
                UserAgent   = UserAgent,
                Token       = _rngGenerator.GetGuid()
            };

            try
            {
                _db.RefreshTokens.Add(newRefreshToken);
                _db.RefreshTokens.Update(dbToken);
                _db.SaveChanges();
                var jwt = _tokenGenerator.GenerateToken(dbUser.UserName, dbUser.Role);

                _logger.LogDebug("Old tokens expired, new created ({RefreshToken}) and JWT generated for user: {UserName}", newRefreshToken.Token, dbUser.UserName);
                return(Ok(new AuthResult()
                {
                    JwtToken = jwt,
                    UserName = dbUser.UserName,
                    RefreshToken = newRefreshToken.Token
                }));
            }
            catch (SecurityTokenEncryptionFailedException e)
            {
                _logger.LogError(e, "Problem with generating JWT for {UserName}", dbUser.UserName);
                throw;
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Problem with applying changes to db");
                throw;
            }
        }
예제 #4
0
 public async Task UpdateRefreshToken(RefreshToken token)
 {
     try
     {
         var dbModel = new DbRefreshToken(token);
         using (var connection = await GetConnectionAsync())
         {
             await connection.ExecuteAsync(RegistrarQueries.RefreshTokenUpdate, dbModel);
         }
     }
     catch (Exception e)
     {
         if (e is RecordNotFoundException)
         {
             throw;
         }
         throw new Exception("Could not update Refresh Token");
     }
 }
예제 #5
0
        private async Task <AuthenticationResult> GenerateAuthenticationResultForUserAsync(IdentityUser user)
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var token        = this.GenerateJwtToken(user);
            var refreshToken = new DbRefreshToken
            {
                Token        = this.GenerateRefreshToken(),
                JwtId        = token.Id,
                UserId       = user.Id,
                CreationDate = DateTime.UtcNow,
                ExpiryDate   = DateTime.UtcNow.AddDays(10),
            };

            await this.identityContext.RefreshTokens.AddAsync(refreshToken);

            await this.identityContext.SaveChangesAsync();

            return(new AuthenticationResult
            {
                Success = true,
                Token = tokenHandler.WriteToken(token),
                RefreshToken = refreshToken.Token,
            });
        }
예제 #6
0
        public IActionResult Login([FromQuery] UserLoginModel loginModel)
        {
            _logger.LogTrace("Login attempt from {RemoteIp} and {UserAgent} with user name {UserName}", UserIp, UserAgent, loginModel.UserName);
            var dbUser = _db.Users.FirstOrDefault(u => u.UserName == loginModel.UserName);

            if (dbUser == null)
            {
                //TODO: maybe change to generalized error
                _logger.LogTrace("User name {UserName} not exist", loginModel.UserName);
                ModelState.AddModelError("User", "user not found");
                return(BadRequest(new ValidationProblemDetails(ModelState)));
            }
            try
            {
                if (dbUser.State == EUserState.InChallenge)
                {
                    return(Forbid(new AuthenticationProperties(new Dictionary <string, string> {
                        { "Challenge", "need pass" }
                    })));
                }
                switch (dbUser.VerifyPassword(loginModel.Password))
                {
                case PasswordVerificationResult.Failed:
                    _logger.LogTrace("User {UserName} send wrong password", loginModel.UserName);
                    ModelState.AddModelError("Password", "Wrong password");
                    return(BadRequest(new ValidationProblemDetails(ModelState)));

                case PasswordVerificationResult.SuccessRehashNeeded:
                {
                    dbUser.HashPasswordAndSet(loginModel.Password);
                    _db.Users.Update(dbUser);
                    break;
                }
                }

                var refreshToken = new DbRefreshToken()
                {
                    Fingerprint = loginModel.Fingerprint,
                    FromTime    = _now,
                    ToTime      = _now.AddDays(_authOptions.RefreshTokenLifetimeDays),
                    CreatedIp   = UserIp,
                    NavUser     = dbUser,
                    UserAgent   = UserAgent,
                    Token       = _rngGenerator.GetGuid()
                };

                _db.RefreshTokens.Add(refreshToken);
                _db.SaveChanges();

                var jwt = _tokenGenerator.GenerateToken(dbUser.UserName, dbUser.Role);
                return(Ok(new AuthResult()
                {
                    JwtToken = jwt,
                    RefreshToken = refreshToken.Token,
                    UserName = dbUser.UserName
                }));
            }
            catch (SecurityTokenEncryptionFailedException e)
            {
                _logger.LogError(e, "Problem with generating JWT for {UserName}", dbUser.UserName);
                throw;
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Problem with applying changes to db");
                throw;
            }
        }