Bảo mật API với Refresh Token trong C# – Phần 20

Đăng ngày: 20/06/2026 • Tác giả: Quản trị viên
Bảo mật API với Refresh Token trong C# – Phần 20

 

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:

  1. Cấu hình JWT trong appsettings.json.
  2. Tạo API đăng nhập để cấp Access Token & Refresh Token.
  3. Xây dựng API refresh để lấy Access Token mới.
  4. Lưu Refresh Token tạm thời để kiểm tra tính hợp lệ.
  5. 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 🚀

Bài viết liên quan