Authentication
Xác thực danh tính trong ASP.NET Core
Các phương pháp Authentication
ASP.NET Core hỗ trợ nhiều scheme xác thực khác nhau, mỗi loại phù hợp với một kiến trúc ứng dụng riêng:
Cookie Auth
Lưu phiên đăng nhập qua cookie trình duyệt
JWT Bearer
Token stateless cho API, không lưu trạng thái server
OAuth / OIDC
Đăng nhập qua bên thứ ba như Google, Facebook
ASP.NET Identity
Framework quản lý user đầy đủ với database
Cookie Authentication
Cách phổ biến nhất cho web apps. Server tạo cookie chứa thông tin phiên đăng nhập, browser tự động gửi cookie trong mỗi request.
Flow: Cookie Authentication
Cấu hình Cookie Authentication
// Program.cs builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.LoginPath = "/Account/Login"; // Redirect khi chưa đăng nhập options.AccessDeniedPath = "/Account/Denied"; // Redirect khi không có quyền options.ExpireTimeSpan = TimeSpan.FromHours(8); // Cookie hết hạn sau 8 giờ options.SlidingExpiration = true; // Tự động gia hạn });
Login Action
// AccountController.cs [HttpPost("login")] public async Task<IActionResult> Login(LoginModel model) { var user = await _userService.ValidateAsync(model.Username, model.Password); if (user == null) return Unauthorized(); var claims = new List<Claim> { new Claim(ClaimTypes.Name, user.Username), new Claim(ClaimTypes.Email, user.Email), new Claim(ClaimTypes.Role, user.Role) }; var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var principal = new ClaimsPrincipal(identity); await HttpContext.SignInAsync(principal); // Tạo cookie và gửi cho browser return RedirectToAction("Index", "Home"); }
SlidingExpiration = true nghĩa là mỗi lần user truy cập, thời hạn cookie được reset. User chỉ bị
logout nếu không hoạt động trong khoảng ExpireTimeSpan.
JWT Bearer Token
Phương pháp phổ biến cho API. Token tự chứa thông tin user, server không cần lưu session.
JWT Anatomy
Một JWT gồm 3 phần, ngăn cách bởi dấu chấm. Click vào từng phần để xem chi tiết:
{
"alg": "HS256",
"typ": "JWT"
}
Header được encode bằng Base64Url, tạo thành phần đầu tiên của token.
{
"sub": "1234567890",
"email": "user@bugcreators.tech",
"role": "Admin",
"jti": "a1b2c3d4-e5f6-7890",
"exp": 1700000000,
"iss": "https://bugcreators.tech"
}
Lưu ý: Payload chỉ được encode, không được mã hóa. Ai cũng có thể đọc nội dung. Không bao giờ đặt mật khẩu hay thông tin nhạy cảm trong payload!
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret_key
)
Server dùng secret key để tạo signature. Khi nhận token, server tính lại signature và so sánh. Nếu khác nhau → token đã bị tamper.
Flow: JWT Authentication
Cấu hình JWT Authentication
// Program.cs builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = "https://bugcreators.tech", ValidAudience = "https://bugcreators.tech", IssuerSigningKey = new SymmetricSecurityKey( Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!)) }; });
Tạo JWT Token
public string GenerateToken(User user) { var claims = new[] { new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()), new Claim(JwtRegisteredClaimNames.Email, user.Email), new Claim(ClaimTypes.Role, user.Role), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]!)); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken( issuer: "https://bugcreators.tech", audience: "https://bugcreators.tech", claims: claims, expires: DateTime.UtcNow.AddHours(2), signingCredentials: creds); return new JwtSecurityTokenHandler().WriteToken(token); }
OAuth 2.0 & OpenID Connect
Cho phép user đăng nhập qua bên thứ ba (Google, Facebook, GitHub) mà không cần tự quản lý password.
OAuth 2.0 Authorization Code Flow
Cấu hình Google OAuth
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
})
.AddCookie()
.AddGoogle(options =>
{
options.ClientId = builder.Configuration["Google:ClientId"]!;
options.ClientSecret = builder.Configuration["Google:ClientSecret"]!;
options.Scope.Add("email");
options.Scope.Add("profile");
});
.AddGoogle(), ASP.NET Core tự động sử dụng OIDC.
ASP.NET Identity Framework
Framework đầy đủ cho quản lý user: đăng ký, đăng nhập, quên mật khẩu, xác thực email, 2FA... Được tích hợp sẵn với Entity Framework Core.
Kiến trúc phân lớp
Cấu hình Identity
// Program.cs builder.Services.AddIdentity<ApplicationUser, IdentityRole>(options => { options.Password.RequireDigit = true; options.Password.RequiredLength = 8; options.Lockout.MaxFailedAccessAttempts = 5; options.User.RequireUniqueEmail = true; }) .AddEntityFrameworkStores<AppDbContext>() .AddDefaultTokenProviders();
So sánh các phương pháp
Mỗi phương pháp có ưu và nhược điểm riêng. Lựa chọn phụ thuộc vào kiến trúc ứng dụng:
| Phương pháp | Phù hợp cho | Ưu điểm | Nhược điểm |
|---|---|---|---|
| Cookie | Web app truyền thống (MVC, Razor Pages) | Đơn giản, browser tự quản lý, hỗ trợ SlidingExpiration | Không phù hợp cho API/mobile, dễ bị CSRF nếu không cấu hình đúng |
| JWT Bearer | REST API, SPA, Mobile app, Microservices | Stateless, dễ scale, cross-domain, chứa claims trong token | Không thể revoke token ngay lập tức, kích thước lớn hơn cookie |
| OAuth / OIDC | Đăng nhập qua bên thứ ba (social login) | Không cần quản lý password, UX tốt, tin cậy từ provider lớn | Phụ thuộc provider bên ngoài, cấu hình phức tạp hơn |
| Identity | Web app cần quản lý user đầy đủ | Đầy đủ tính năng (2FA, email confirm, lockout), tích hợp EF Core | Nặng cho ứng dụng nhỏ, phụ thuộc database, learning curve cao |