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; } }
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; } }