Пример #1
0
        private async Task <JwtAuthenticationResult> CreateAuthenticationResultFromUserAsync(ApplicationUser user)
        {
            var roles = await _userManager.GetRolesAsync(user);

            var handler = new JwtSecurityTokenHandler();
            var claims  = new List <Claim>();

            claims.Add(new Claim(ClaimTypes.Name, user.UserName));
            claims.Add(new Claim(ClaimTypes.NameIdentifier, user.Id));
            claims.Add(new Claim(JwtRegisteredClaimNames.Aud, _tokenValidationParameters.ValidAudience));
            claims.AddRange(roles.Select(d => new Claim(ClaimTypes.Role, d)));

            var securityKey   = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_options.Value.Key));
            var securityToken = new JwtSecurityToken(
                _options.Value.Issuer,
                claims: claims,
                signingCredentials: new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha512),
                expires: DateTime.UtcNow.Add(_options.Value.AccessTokenValidDuration));

            var outputToken  = handler.WriteToken(securityToken);
            var refreshToken = GenerateRefreshToken();

            await _refreshTokenManager.AddRefreshTokenAsync(user, refreshToken, DateTime.UtcNow.Add(_options.Value.RefreshTokenValidDuration));

            return(new JwtAuthenticationResult()
            {
                AccessToken = outputToken,
                RefreshToken = refreshToken
            });
        }
Пример #2
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;
                }
            }
Пример #3
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;
            }
        }