예제 #1
0
        public async Task <AuthenticationResponse> RefreshAuthenticationAsync(AuthenticationResponse request)
        {
            var principal = GetPrincipalFromAccessToken(request.AccessToken);

            if (principal == null)
            {
                _logger.LogWarning($"[{nameof(RefreshAuthenticationAsync)}] Unable to get principal from access token '{request.AccessToken}'.");
                throw new AuthenticationServiceUnauthorizedException();
            }

            var user = _userManager.Users.Include(u => u.RefreshTokens).SingleOrDefault(u => u.Id == principal.FindFirstValue(ClaimTypes.NameIdentifier));

            if (user == null)
            {
                _logger.LogWarning($"[{nameof(RefreshAuthenticationAsync)}] User '{user.Id}' not found.");
                throw new AuthenticationServiceUnauthorizedException();
            }

            var existingRefreshToken = user.RefreshTokens.SingleOrDefault(t => t.Token == request.RefreshToken);

            if (!user.IsEnabled || existingRefreshToken == null || (DateTime.UtcNow > existingRefreshToken.ExpiresUtc))
            {
                _logger.LogInformation($"[{nameof(RefreshAuthenticationAsync)}] Refresh token '{request.RefreshToken}' in invalid.  Reason: {(!user.IsEnabled ? "User is disabled" : existingRefreshToken == null ? "Token not found" : DateTime.UtcNow > existingRefreshToken.ExpiresUtc ? "Token Expired" : "Unknown")}.");
                throw new AuthenticationServiceForbiddenException();
            }

            var success = user.RefreshTokens.Remove(existingRefreshToken);

            _logger.LogInformation($"[{nameof(RefreshAuthenticationAsync)}] Removed refresh token '{existingRefreshToken.Token}' for user '{existingRefreshToken.UserId}'.  Success: '{success}'.");

            var refreshToken = await AuthenticationResponse.GenerateRefreshTokenAsync();

            user.RefreshTokens.Add(new RefreshToken {
                ExpiresUtc = DateTime.UtcNow.Add(Options.BearerRefreshTokenLifespan), Token = refreshToken
            });
            var result = await _userManager.UpdateAsync(user);

            _logger.LogInformation($"[{nameof(RefreshAuthenticationAsync)}] Added refresh token '{refreshToken}' for user '{existingRefreshToken.UserId}'.  Success: '{result.Succeeded}'.");

            return(new AuthenticationResponse
            {
                AccessToken = GetAccessTokenForUser(user),
                RefreshToken = refreshToken
            });
        }
예제 #2
0
        public async Task <AuthenticationResponse> AuthenticateAsync(AuthenticationRequest request)
        {
            var user = await _userManager.FindByIdAsync(request.Id);

            if (user == null)
            {
                _logger.LogWarning($"[{nameof(AuthenticateAsync)}] User '{request.Id}' not found.");
                throw new AuthenticationServiceUnauthorizedException();
            }

            if (!user.IsEnabled)
            {
                _logger.LogWarning($"[{nameof(AuthenticateAsync)}] User '{user.Id}' is disabled.");
                throw new AuthenticationServiceForbiddenException();
            }

            if (!await _userManager.VerifyUserTokenAsync(user, Options.OtpProvider, Options.OtpPurpose, request.Token))
            {
                _logger.LogWarning($"[{nameof(AuthenticateAsync)}] User '{user.Id}' one-time-password token '{request.Token}' verification failed.");
                throw new AuthenticationServiceForbiddenException();
            }

            var refreshToken = await AuthenticationResponse.GenerateRefreshTokenAsync();

            user.RefreshTokens.Add(new RefreshToken {
                ExpiresUtc = DateTime.UtcNow.Add(Options.BearerRefreshTokenLifespan), Token = refreshToken
            });
            var result = await _userManager.UpdateAsync(user);

            _logger.LogInformation($"[{nameof(AuthenticateAsync)}] Added refresh token '{refreshToken}' for user '{user.Id}'.  Success: '{result.Succeeded}'.");

            // This ensures the OTP cannot be used again.
            result = await _userManager.UpdateSecurityStampAsync(user);

            _logger.LogInformation($"[{nameof(AuthenticateAsync)}] Updated security stamp for user '{user.Id}'.  Success: '{result.Succeeded}'.");

            return(new AuthenticationResponse
            {
                AccessToken = GetAccessTokenForUser(user),
                RefreshToken = refreshToken
            });
        }