Bảo mật API với Refresh Token trong C# – Phần 20
1. Giới thiệu về Refresh Token
🔹 Trong JWT Authentication, khi Access Token hết hạn, người dùng cần đăng nhập lại. Điều này gây bất tiện.
🔹 Refresh Token giúp người dùng yêu cầu Access Token mới mà không cần đăng nhập lại.
📌 Lợi ích của Refresh Token:
✅ Tránh yêu cầu đăng nhập nhiều lần.
✅ Cải thiện bảo mật bằng cách kiểm soát thời gian sống của Access Token.
✅ Giảm tải hệ thống xác thực.
2. Cấu hình Refresh Token trong ASP.NET Core
Thêm cấu hình JWT vào appsettings.json
"Jwt": {
"Key": "Your_Secret_Key_123456789",
"Issuer": "yourdomain.com",
"Audience": "yourdomain.com",
"AccessTokenExpirationMinutes": 15,
"RefreshTokenExpirationDays": 7
}
📌 Access Token hết hạn sau 15 phút, Refresh Token sau 7 ngày.
3. Cập nhật AuthController.cs để hỗ trợ Refresh Token
Thêm lớp TokenModel.cs để lưu trữ Token
public class TokenModel
{
public string AccessToken { get; set; }
public string RefreshToken { get; set; }
}
Thêm danh sách lưu Refresh Token tạm thời
private static List<(string Username, string RefreshToken)> _refreshTokens = new();
4. Tạo API Đăng Nhập với Refresh Token
[HttpPost("login")]
public IActionResult Login([FromBody] UserLogin user)
{
if (user.Username == "admin" && user.Password == "123456") // Kiểm tra user từ DB
{
var accessToken = GenerateJwtToken(user.Username);
var refreshToken = GenerateRefreshToken();
_refreshTokens.Add((user.Username, refreshToken));
return Ok(new TokenModel
{
AccessToken = accessToken,
RefreshToken = refreshToken
});
}
return Unauthorized();
}
📌 Mỗi lần đăng nhập sẽ tạo mới Access Token & Refresh Token.
5. API Refresh Token
[HttpPost("refresh")]
public IActionResult Refresh([FromBody] TokenModel tokenModel)
{
var storedToken = _refreshTokens.FirstOrDefault(t => t.RefreshToken == tokenModel.RefreshToken);
if (storedToken.Username == null)
{
return Unauthorized();
}
var newAccessToken = GenerateJwtToken(storedToken.Username);
var newRefreshToken = GenerateRefreshToken();
// Cập nhật refresh token mới
_refreshTokens.Remove(storedToken);
_refreshTokens.Add((storedToken.Username, newRefreshToken));
return Ok(new TokenModel
{
AccessToken = newAccessToken,
RefreshToken = newRefreshToken
});
}
📌 Nếu Refresh Token hợp lệ, hệ thống cấp mới Access Token & Refresh Token.
6. Hàm tạo Access Token & Refresh Token
private string GenerateJwtToken(string username)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(ClaimTypes.Name, username),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var token = new JwtSecurityToken(
_config["Jwt:Issuer"],
_config["Jwt:Audience"],
claims,
expires: DateTime.UtcNow.AddMinutes(Convert.ToDouble(_config["Jwt:AccessTokenExpirationMinutes"])),
signingCredentials: creds
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
private string GenerateRefreshToken()
{
return Convert.ToBase64String(RandomNumberGenerator.GetBytes(64));
}
📌 Access Token có thời gian sống ngắn, Refresh Token dài hơn và ngẫu nhiên.
7. Kiểm thử API Refresh Token
📌 1. Đăng nhập để lấy Access Token & Refresh Token
✅ Gửi POST request đến api/auth/login với JSON:
{
"username": "admin",
"password": "123456"
}
✅ Nhận về:
{
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "tX6qG9dfGp5P..."
}
📌 2. Khi Access Token hết hạn, gửi Refresh Token để lấy Token mới
✅ Gửi POST request đến api/auth/refresh với JSON:
{
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "tX6qG9dfGp5P..."
}
✅ Nhận về Access Token & Refresh Token mới:
{
"accessToken": "newAccessToken123...",
"refreshToken": "newRefreshTokenABC..."
}
📌 API của bạn sẽ tiếp tục hoạt động mà không cần đăng nhập lại.
8. Xóa Refresh Token khi Đăng Xuất
[HttpPost("logout")]
public IActionResult Logout([FromBody] TokenModel tokenModel)
{
var storedToken = _refreshTokens.FirstOrDefault(t => t.RefreshToken == tokenModel.RefreshToken);
if (storedToken.Username != null)
{
_refreshTokens.Remove(storedToken);
}
return Ok(new { message = "Đăng xuất thành công" });
}
📌 Khi đăng xuất, Refresh Token sẽ bị vô hiệu hóa.
9. Tổng Kết
✅ Access Token ngắn hạn giúp bảo mật API.
✅ Refresh Token giúp cấp Access Token mới mà không cần đăng nhập lại.
✅ Cần lưu Refresh Token cẩn thận để tránh rủi ro bảo mật.
📌 Các bước chính:
- Cấu hình JWT trong
appsettings.json. - Tạo API đăng nhập để cấp Access Token & Refresh Token.
- Xây dựng API
refreshđể lấy Access Token mới. - Lưu Refresh Token tạm thời để kiểm tra tính hợp lệ.
- Thêm API
logoutđể xóa Refresh Token khi người dùng đăng xuất.
💡 Bài tiếp theo:
👉 Xây dựng hệ thống phân quyền Role-based Authentication trong C# – Phần 21 🚀