SSO hoạt động như thế nào? Tự xây hệ thống SSO bằng ASP.NET Core
Bạn đã bao giờ thắc mắc: Tại sao mình vừa đăng nhập vào Gmail, lượn sang YouTube đã thấy avatar mình chễm chệ ở góc phải, rồi tạt qua Google Drive cũng không cần gõ lại password? Google có "phép thuật" đọc tâm trí người dùng chăng?
Hoàn toàn không! Chào mừng bạn đến với thế giới của SSO (Single Sign-On).
Hãy thử nhìn vào trải nghiệm quen thuộc này của bạn:
- Mở Gmail → đã đăng nhập
- Mở YouTube → vẫn đăng nhập
- Mở Google Drive → vẫn đăng nhập.
Bạn không cần login lại.
Cảm giác giống như Google đang nói:
"Đăng nhập một lần thôi, phần còn lại để tôi lo."
Đó chính là Single Sign-On (SSO).
SSO là cơ chế cho phép người dùng đăng nhập một lần nhưng truy cập được nhiều hệ thống.
Trong bài viết này chúng ta sẽ cùng khám phá:
- SSO thực sự hoạt động như thế nào
- OAuth2 Flow phía sau Google Login
- Kiến trúc của một hệ thống SSO
- Và cách xây dựng nó bằng ASP.NET Core
Nếu bạn từng muốn xây hệ thống login giống Google hoặc Facebook, bài viết này dành cho bạn.
1. SSO thực sự hoạt động như thế nào?
Hãy tưởng tượng hệ sinh thái ứng dụng của bạn là một Khu vui chơi giải trí (Vinpearl, Sun World...).
Nếu không có SSO: Bạn muốn chơi tàu lượn siêu tốc? Mua vé. Muốn vào nhà ma? Mua vé tiếp. Muốn đi bơi? Lại xếp hàng mua vé. Khá là bực mình đúng không?
Khi có SSO: Bạn chỉ cần đến cổng chính (Identity Provider), xuất trình CCCD một lần duy nhất. Bảo vệ sẽ đeo cho bạn một cái Vòng tay VIP. Từ đó trở đi, bạn đi tới bất kỳ trò chơi nào (Gmail, YouTube, Drive...), nhân viên chỉ cần nhìn vòng tay là cho bạn vào.
SSO chính là cái Cổng chính đó. Nó tập trung việc xác thực vào một nơi duy nhất. Các ứng dụng con không thèm quan tâm mật khẩu của bạn là gì, chúng chỉ tin tưởng vào "Vòng tay VIP" do Cổng chính cấp phát.
Bây giờ chúng ta ánh xạ qua hệ thống phần mềm nhé:
Trong ví dụ này:
- Cổng chính → Identity Provider (SSO Server)
- Vòng tay VIP → Access Token
- Các trò chơi → Các ứng dụng (Gmail, YouTube, Drive...)
Các ứng dụng con không cần biết mật khẩu của bạn là gì. Chúng chỉ cần kiểm tra:
"Token này có được cấp bởi SSO Server không?"
Nếu hợp lệ → cho truy cập.
Sơ đồ tổng quan cách SSO hoạt động:
Đó chính là ý tưởng cốt lõi của Single Sign-On (SSO):
Đăng nhập một lần → truy cập nhiều hệ thống mà không cần login lại.
Sau khi hiểu được ý tưởng này, câu hỏi tiếp theo sẽ là:
Chiếc “vòng tay VIP” (token) đó được tạo ra như thế nào?
Câu trả lời nằm ở OAuth2 Flow — cơ chế đứng sau hầu hết các hệ thống đăng nhập hiện đại như Google Login hay Facebook Login.
2. Lật tẩy OAuth2 Flow đằng sau "Login with Google"
Google không tự nhiên phát minh ra “bánh xe”. Họ sử dụng một tiêu chuẩn công nghiệp phổ biến gọi là OAuth2 (kết hợp với OpenID Connect) để xử lý việc đăng nhập và cấp quyền truy cập.
Khi bạn bấm nút “Login with Google”, phía sau hậu trường sẽ diễn ra một chuỗi bước khá thú vị gần giống như một bộ phim hành động diễn ra trong vài mili-giây
))
Quá trình này được gọi là Authorization Code Flow.
Bước 1 – Client chuyển hướng người dùng đến Google
Khi người dùng bấm Login with Google, ứng dụng của bạn (Client) sẽ nói với Google:
"Ê Google, ông khách này muốn dùng app của tui, xác thực ổng giùm cái!"
Lúc này ứng dụng sẽ redirect người dùng sang trang đăng nhập của Google.
Bước 2 – Google xác thực người dùng
Google (Identity Provider) sẽ hiển thị màn hình đăng nhập:
"Xin chào, vui lòng nhập Email và Password của bạn."
Sau khi đăng nhập xong, Google sẽ hỏi thêm một câu:
"Ứng dụng này muốn truy cập thông tin email của bạn. Bạn có đồng ý không?"
Người dùng có thể Allow hoặc Deny quyền truy cập.
Bước 3 – Google cấp Authorization Code
Nếu người dùng đồng ý, Google sẽ không trả Token ngay lập tức.
Thay vào đó, Google sẽ cấp một mã tạm thời gọi là Authorization Code, rồi redirect người dùng quay trở lại ứng dụng của bạn.
Authorization Code giống như một tờ giấy chứng nhận tạm thời.
Bước 4 – Client đổi Authorization Code lấy Token
Bây giờ ứng dụng của bạn sẽ lấy Authorization Code đó và thực hiện một bước phía sau hậu trường.
Server của ứng dụng sẽ gọi API trực tiếp đến Google để đổi Authorization Code lấy:
-
Access Token
-
ID Token (nếu dùng OpenID Connect)
Token này chính là “Vòng tay VIP” mà chúng ta nói ở phần trước.
Và ở đây bạn có thắc mắc là:
Tại sao Google không trả Token luôn ở bước 3 cho nhanh không?
-> Câu trả lời là bảo mật.
Nếu Google trả Token ngay lúc redirect về trình duyệt, Token sẽ xuất hiện trong URL của browser. Điều này rất nguy hiểm vì:
- Token có thể bị lộ qua browser history
- Token có thể bị lộ qua log server
- Token có thể bị đánh cắp qua referrer
Thay vào đó, Google chỉ trả về Authorization Code.
Sau đó server của ứng dụng sẽ âm thầm dùng code này để đổi lấy Token thông qua kênh giao tiếp server-to-server an toàn.
Nhờ vậy, Token sẽ không bao giờ bị lộ ra ngoài trình duyệt.
3. Kiến trúc của một hệ thống SSO: “Chia để trị!”
Để dễ hình dung, hãy tưởng tượng toàn bộ hệ thống phần mềm của bạn giống như một tòa nhà văn phòng lớn.
Kiến trúc SSO sẽ chia tòa nhà này thành hai khu vực rõ ràng, mỗi bên có nhiệm vụ riêng và không ai giẫm chân lên ai.
Phe 1: “Phòng An Ninh” — Identity Provider
Đây là trung tâm xác thực của toàn bộ hệ thống.
Trong thực tế kiến trúc phần mềm khi hệ thống được tách thành microservices, thành phần này thường được gọi là:
IAM — Identity and Access Management
Nhiệm vụ của Identity Provider:
- Lưu trữ thông tin người dùng
- Quản lý đăng nhập / đăng ký
- Xác thực tài khoản và mật khẩu
- Cấp Token sau khi xác thực thành công
Có thể tưởng tượng IdP giống như phòng an ninh của tòa nhà.
Sau khi xác minh danh tính của bạn, họ sẽ cấp cho bạn một Token để bạn có thể đi vào các khu vực khác trong tòa nhà.
Phe 2: “Các phòng ban nghiệp vụ” — Service Providers / Client Apps
Đây chính là các ứng dụng hoặc dịch vụ nghiệp vụ trong hệ thống.
Ví dụ:
- Web Application
- Mobile Application
- Backend APIs
Điểm đặc biệt là:
Các ứng dụng này không bao giờ lưu mật khẩu người dùng.
Khi người dùng truy cập, ứng dụng sẽ không hỏi mật khẩu mà chỉ kiểm tra:
"Bạn có Token hợp lệ không?"
Nếu Token hợp lệ và được ký bởi Identity Provider, ứng dụng sẽ cho phép truy cập.
💡 Chốt lại lợi ích:
Cách chia này giúp các developer ngủ ngon hơn vào ban đêm. Giả sử cái Web App nghiệp vụ của bạn có bị hacker tìm ra lỗ hổng và tấn công, chúng cũng không thể nào lấy cắp được mật khẩu người dùng vì bản thân cái Web App đó làm gì có lưu mật khẩu mà lấy!. Toàn bộ thông tin nhạy cảm nhất đã được "Phòng An Ninh" ôm trọn và bảo vệ trong một pháo đài riêng biệt rồi hehe
)
4. Bắt tay vào việc: Xây dựng SSO bằng ASP.NET Core
Sau khi hiểu cách SSO hoạt động, chúng ta hãy thử xây dựng một hệ thống SSO demo đơn giản bằng ASP.NET Core. Trong demo này chúng ta sẽ có 2 thành phần:
SSO Server (Auth Server)
Client Application
SSO Server chịu trách nhiệm:
- xác thực người dùng
- cấp token
Client App sẽ:
- redirect user tới SSO Server để login
- nhận token sau khi đăng nhập thành công
SSO Server
Bước 1: Tạo SSO Server
dotnet new webapi -n SsoServer
Cài package JWT:
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
Bước 2: Tạo API Login
API này sẽ xác thực user và cấp token.
Create Token Service
public class TokenService
{
private readonly IConfiguration _config;
public TokenService(IConfiguration config)
{
_config = config;
}
public string GenerateToken(string username)
{
// Create claims (information stored inside the token)
var claims = new[]
{
new Claim(ClaimTypes.Name, username),
new Claim("role", "super-admin")
};
// Create the signing key from configuration
var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_config["Jwt:SecretKey"])
);
var credentials = new SigningCredentials(
key,
SecurityAlgorithms.HmacSha256
);
// Create the JWT token
var token = new JwtSecurityToken(
issuer: "https://my-sso-server.com", // The server issuing the token
audience: "my-microservices", // The intended audience
claims: claims,
expires: DateTime.UtcNow.AddMinutes(30),
signingCredentials: credentials
);
// Serialize the token to string
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
Inject Service vào Controller
[ApiController]
[Route("api/auth")]
public class AuthController : ControllerBase
{
private readonly TokenService _tokenService;
public AuthController(TokenService tokenService)
{
_tokenService = tokenService;
}
[HttpPost("token")]
public IActionResult GenerateToken([FromBody] LoginRequest request)
{
// Validate user credentials (hardcoded for demo purposes)
if (request.Username != "admin" || request.Password != "123456")
return Unauthorized("Invalid username or password");
var token = _tokenService.GenerateToken(request.Username);
return Ok(new
{
access_token = token,
});
}
}
Sau khi login thành công, server sẽ trả về:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Đây chính là “vòng tay VIP” mà chúng ta đã nói ở phần trước.
Client App sử dụng Token
Ví dụ đây là các project API xử lý logic kinh doanh. Nó không hề biết user/pass là gì, và cũng không cần kết nối tới bảng Users. Nó chỉ cần biết "Cách đọc Token do SSO Server cấp".
Bước 1: Tạo project API nghiệp vụ
dotnet new webapi -n ProductApi
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
Bước 2: Cấu hình ở Program.cs
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "https://my-sso-server.com",
ValidAudience = "my-microservices",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("KEY_SSO_SERVER"))
};
});
builder.Services.AddAuthorization();
Bước 3: Controller
Gắn [Authorize] vào bất kỳ API nào bạn muốn khóa lại.
[ApiController]
[Route("api/products")]
[Authorize]
public class ProductController : ControllerBase
{
[HttpGet("vip-items")]
public IActionResult GetVipProducts()
{
var username = User.Identity.Name;
return Ok($"Welcome {username} to the VIP warehouse!");
}
}
Tổng kết
SSO giúp người dùng đăng nhập một lần nhưng truy cập được nhiều hệ thống khác nhau. Bằng cách tách riêng Identity Provider và sử dụng Token để xác thực, các ứng dụng không cần xử lý mật khẩu người dùng mà chỉ cần kiểm tra token hợp lệ.
Trong bài viết này, chúng ta đã:
- Hiểu cách SSO hoạt động
- Tìm hiểu OAuth2 Authorization Code Flow
- Xây dựng một demo SSO đơn giản bằng ASP.NET Core và JWT
Hy vọng sau bài viết này, mỗi khi bấm nút "Login with Google", bạn sẽ không chỉ thấy một cái loading spinner nhàm chán, mà sẽ tưởng tượng ra cả một bộ phim hành động gay cấn của các luồng trao đổi Token ở hậu trường! 🚀
All rights reserved