Пример #1
0
        public async Task <IActionResult> LoginAsync([FromBody] LoginViewModel loginData)
        {
            _logger.LogInformation($"Starting method '{nameof(LoginAsync)}'.");

            var user = await _userManager.FindByNameAsync(loginData.UserName);

            if (!(user is null) && await _userManager.CheckPasswordAsync(user, loginData.Password))
            {
                try
                {
                    _logger.LogDebug("User found.");
                    var userRoles = await _userManager.GetRolesAsync(user);

                    var    jwtToken        = _jwtTokenHandler.CreateJwtToken(user, userRoles.ToArray());
                    string accessToken     = _jwtTokenHandler.WriteJwtToken(jwtToken);
                    var    newRefreshToken = _refreshTokenMananger.GenerateRefreshToken();

                    // Save refresh token to the database for future exachange.
                    await _refreshTokenMananger.AddRefreshTokenAsync(newRefreshToken);

                    var loginInfo = new LoginInfo
                    {
                        User = new UserDto {
                            Id = user.Id, UserName = user.UserName, LoggedOn = DateTime.UtcNow
                        },
                        AccessToken  = new AccessToken(accessToken, (int)jwtToken.Payload.Exp),
                        RefreshToken = MapToDto(newRefreshToken)
                    };
                    var response = new ResponseWrapper(loginInfo);

                    _jwtTokenHandler.GetPrincipalFromJwtToken(accessToken);

                    _logger.LogInformation($"Finished method '{nameof(LoginAsync)}'.");
                    return(Ok(response));
                }
                catch (Exception ex)
                {
                    LogUnexpectedException(ex);
                    throw;
                }
            }
Пример #2
0
        public async Task <IActionResult> RefreshTokenExchangeAsync([FromBody] RefreshTokenViewModel refreshTokenData)
        {
            _logger.LogInformation($"Starting method '{nameof(RefreshTokenExchangeAsync)}'.");

            try
            {
                _logger.LogDebug($"Getting principal from passed access token.");
                var claims = _jwtTokenHandler.GetPrincipalFromJwtToken(refreshTokenData.AccessToken, true);

                // Get expiry date of the access token. If it's not before UtcNow then return 400 BadRequest.
                var expiryDate = DateTimeOffset.FromUnixTimeSeconds(int.Parse(claims.FindFirstValue(JwtRegisteredClaimNames.Exp)));
                if (expiryDate.DateTime > DateTime.UtcNow)
                {
                    return(OnInvalidParameterError($"The access token passed has not expired."));
                }

                // Check if passed refresh token matches any saved refresh token.
                _logger.LogDebug("Checking refresh token correctness.");
                var savedRefreshToken = await _refreshTokenManager.GetSavedRefreshTokenAsync(refreshTokenData.RefreshToken);

                // Check if refresh token expired.
                if (IsRefreshTokenExpired(savedRefreshToken))
                {
                    return(OnInvalidParameterError($"The refresh token passed has expired."));
                }

                // Create temporary user representation based on access token principal.
                var tempUser = new IdentityUser
                {
                    Id       = claims.FindFirstValue(JwtRegisteredClaimNames.NameId),
                    UserName = claims.FindFirstValue(JwtRegisteredClaimNames.Sub),
                    Email    = claims.FindFirstValue(JwtRegisteredClaimNames.Email)
                };

                string[] userRoles = new string[] { claims.FindFirstValue(ApiConstants.RoleClaim) };

                // Generate new access and refresh tokens.
                _logger.LogDebug("Generating new access and refresh tokens.");
                var    newJwtToken     = _jwtTokenHandler.CreateJwtToken(tempUser, userRoles);
                string newAccessToken  = _jwtTokenHandler.WriteJwtToken(newJwtToken);
                var    newRefreshToken = _refreshTokenManager.GenerateRefreshToken();

                // Add new refresh token to the database for future tokens exchange.
                // Delete the saved token to prevent the use of the refresh token more than once.
                _logger.LogDebug("Adding new refresh token to the database.");
                await _refreshTokenManager.AddRefreshTokenAsync(newRefreshToken);

                _logger.LogDebug("Deleting saved refresh token from the database.");
                await _refreshTokenManager.DeleteRefreshTokenAsync(savedRefreshToken);

                var response = new ResponseWrapper(new RefreshTokensResponseDto
                {
                    AccessToken  = new AccessToken(newAccessToken, (int)newJwtToken.Payload.Exp),
                    RefreshToken = MapToDto(newRefreshToken)
                });

                _logger.LogInformation($"Finished method '{nameof(RefreshTokenExchangeAsync)}'.");
                return(Ok(response));
            }
            catch (InvalidOperationException ex)
            {
                return(OnInvalidParameterError($"Invalid refresh token.", ex));
            }
            catch (SecurityTokenException ex)
            {
                return(OnInvalidParameterError($"Invalid access token.", ex));
            }
            catch (Exception ex)
            {
                LogUnexpectedException(ex, ex.Message);
                throw;
            }
        }