Quản lý thông tin đăng nhập, thông tin người dùng, quyền và xác thực là yếu tố then chốt đối với mọi hệ thống. Để đơn giản hóa quá trình này, bài viết này sẽ hướng dẫn xây dựng một Identity Service sử dụng IdentityServer4 và sentayho.com.vn Identity.
Trong một ứng dụng hiện đại, chúng ta thường gặp nhiều thành phần khác nhau như ứng dụng front-end, back-end và các API tích hợp từ bên thứ ba. Vậy, làm thế nào để triển khai xác thực (authentication) và cấp quyền (authorization) một cách hiệu quả?
sentayho.com.vn Core Identity là một thư viện mạnh mẽ, được thiết kế để quản lý xác thực và cấp quyền cho nhiều loại dự án, từ MVC, WebForms đến WebAPI. Nó đáp ứng các nhu cầu sau:
- Dễ dàng tùy chỉnh profile người dùng
- Lưu trữ thông tin người dùng trong cơ sở dữ liệu sử dụng Entity Framework Code First
- Hỗ trợ unit test
- Giới hạn quyền truy cập dựa trên quyền
- Cung cấp cơ chế làm việc với claim
Vậy, tại sao cần IdentityServer4 khi đã có sentayho.com.vn Identity cho Authentication và Authorization?
sentayho.com.vn Identity có thể nhận token bảo mật khi đăng nhập từ bên thứ ba như Facebook, Google, Microsoft và Twitter. Tuy nhiên, nếu bạn muốn tự tạo mã token bảo mật cho các ứng dụng nội bộ, bạn cần một thư viện của bên thứ ba như IdentityServer4 hoặc OpenIddict.
Nghiên cứu cho thấy IdentityServer4 là một lựa chọn phổ biến cho mục đích này.
IdentityServer4 là gì?
IdentityServer4 là một framework mã nguồn mở, hỗ trợ OpenID Connect và OAuth 2.0 trên sentayho.com.vn Core. Nó là một thư viện NuGet, hoạt động như một middleware trong sentayho.com.vn Core, cho phép đăng nhập/đăng xuất, cấp token, xác thực và hỗ trợ các giao thức chuẩn khác.
Để hiểu rõ hơn về kiến trúc của IdentityServer4, bạn có thể tham khảo các thuật ngữ sau:
Kiến trúc tổng quan của IdentityServer4
Nguồn: sentayho.com.vn/en/latest/intro/terminology.html
- User: Người dùng cuối, sử dụng ứng dụng client.
- Client: Ứng dụng phần mềm, ví dụ như trình duyệt web, ứng dụng di động, cần truy cập API resource.
- Resources: Các API cần được bảo vệ bởi IdentityServer4.
- Access Token: Token được sử dụng để truy cập API Resource.
- Refresh Token: Token được sử dụng để lấy lại access token mới khi access token hết hạn, mà không cần sự tương tác của người dùng. Để sử dụng refresh token, cần thiết lập
AllowOfflineAccessthànhtruetrong cấu hình client của IdentityServer4. - Grant Type: Loại tương tác giữa client và IdentityServer. Chọn grant type phù hợp dựa trên loại client.
Xây dựng Identity Service
Các bước chi tiết để xây dựng Identity Service có thể được tìm thấy trong tài liệu của IdentityServer4. Kết quả cuối cùng sẽ là một Visual Studio 2019 solution bao gồm:
- IdentityMicroservice: Dự án chứa IdentityServer4 và sentayho.com.vn Identity.
- ClientsProjectsSPAClient: Ứng dụng client SPA (ví dụ: Angular, React).
- ClientsProjectsWebClient: Ứng dụng client dạng Web MVC.
- ApiResrouceProjectsTestApiResource: Một API cần được bảo vệ.
Các project trong solution Identity Service
1. Khởi tạo Identity Microservice Project
Đây là project chịu trách nhiệm bảo vệ API, cấu hình các client và lưu trữ thông tin người dùng. Mã nguồn đầy đủ có trên GitHub. Dưới đây là các bước thực hiện:
Tạo mới ứng dụng sentayho.com.vn CORE Web Application (Empty).
Tạo ứng dụng sentayho.com.vn Core Web Application (Empty)
Cài đặt IdentityServer4 Templates bằng lệnh sau:
dotnet new -i sentayho.com.vnlates
Thêm IdentityServer4 và QuickStart UI Files (controller và view của Identity, bao gồm đăng nhập, đăng ký…) cùng với sentayho.com.vn Identity NuGet packages vào project bằng lệnh sau:
dotnet new is4aspid -force
Chạy lệnh tạo template IdentityServer4 và sentayho.com.vn Identity
Với .NET Core 3.1
Sau khi chạy lệnh trên, hãy đảm bảo chuyển project từ .NET Core 3.0 lên .NET Core 3.1 và cập nhật IdentityServer4 NuGet Package từ 3.0 lên 3.1. Việc thực thi lệnh có thể ảnh hưởng đến file .csproj và có thể downgrade phiên bản .NET Core.
Cài đặt các NuGet packages sau:
Microsoft.EntityFrameworkCore.ToolsVersion=”3.1.0″
Loại bỏ NuGet package “Microsoft.AspNetCore.App” vì nó không cần thiết trên .NET Core 3.1 và có thể gây lỗi cho ApplicationDbContext và sentayho.com.vn do thiếu các NuGet packages. Cài đặt thêm:
- Microsoft.AspNetCore.Identity.EntityFrameworkCore 3.1.0
- Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore 3.1.0
Bạn có thể nhận được warning message về IHostingEnvironment vì interface này đã được thay thế bởi IWebHostEnvironment trong sentayho.com.vn Core 3.1.
Trong ConfigureServices() của Startup.cs, thêm:
//services.AddMvc().SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_2_1);
sentayho.com.vnontrollersWithViews();
Trong Configure() của Startup.cs, điều chỉnh:
sentayho.com.vnouting();
// Block 4:
// UseIdentityServer include a call to UseAuthentication
sentayho.com.vndentityServer();
sentayho.com.vnuthorization();
//app.UseMvcWithDefaultRoute();
sentayho.com.vnndpoints(endpoints =>
{
sentayho.com.vnontrollerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
Build lại project và kiểm tra
Kết quả sau khi cấu hình thành công Identity Server
2. Cấu hình Identity MicroService Project
Hai file chính cần chỉnh sửa là:
Config.csStartup.cs
Định nghĩa thông tin client và resource
Thiết kế solution cho Identity Server
Nguồn: sentayho.com.vn/en/latest/intro/sentayho.com.vn (modified version)
IdentityServer4 cung cấp hai lựa chọn cấu hình: InMemory hoặc sử dụng database để lưu trữ. Ví dụ này sử dụng InMemory. Tức là danh sách client hoặc danh sách resource có thể được thêm vào database của Identity Server hoặc trực tiếp trong code InMemory. Sử dụng database giúp việc chỉnh sửa và bổ sung dễ dàng hơn.
Trong Config.cs, bạn sẽ định nghĩa danh sách API resources cần bảo vệ và danh sách các client được phép truy cập vào resource. File này sẽ được sử dụng trong bước tiếp theo ở Startup.cs.
Trong kịch bản thực tế, nên sử dụng cấu hình dạng database. IdentityServer4 hỗ trợ SQL Server thông qua EntityFramework Core. Trong ví dụ này, Config.cs có thể như sau:
// Block 1: All APIs, I want to protect in my system
public static IEnumerable<ApiResource> GetApis()
{
return new ApiResource[]
{
new ApiResource("identity.api", "Identity API"),
new ApiResource("test.api","Test API")
};
}
public static IEnumerable<Client> GetClients()
{
return new[]
{
//Block 2: MVC client using hybrid flow
new Client
{
ClientId = "webclient",
ClientName = "Web Client",
RequireConsent = false,
AllowedGrantTypes = sentayho.com.vnidAndClientCredentials,
ClientSecrets = { new Secret("49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".Sha256()) },
RedirectUris = { "https://localhost:5002/signin-oidc" },
FrontChannelLogoutUri = "https://localhost:5002/signout-oidc",
PostLogoutRedirectUris = { "https://localhost:5002/signout-callback-oidc" },
AllowOfflineAccess = true,
AllowedScopes = { "openid", "profile", "identity.api","test.api" }
},
//Block 3: SPA client using Code flow
new Client
{
ClientId = "spaclient",
ClientName = "SPA Client",
ClientUri = "https://localhost:5003",
RequireConsent = false,
AllowedGrantTypes = sentayho.com.vn,
RequirePkce = true,
RequireClientSecret = false,
AllowAccessTokensViaBrowser = true,
RedirectUris = { "https://localhost:5003/index.html", "https://localhost:5003/callback.html" },
PostLogoutRedirectUris = { "https://localhost:5003/index.html" },
AllowedCorsOrigins = { "https://localhost:5003" },
AllowedScopes = { "openid", "profile", "identity.api" ,"test.api" }
}
};
}
Thêm IdentityServer4 và sentayho.com.vn Identity vào middleware
Startup.cs class được gọi khi ứng dụng chạy. Nó có hai phương thức: ConfigureServices() đăng ký các service trong DI Container được sử dụng trong ứng dụng, và Configure() cấu hình Request Pipeline:
public void ConfigureServices(IServiceCollection services)
{
//TODO: change UseSqlite to UseSqlServer
sentayho.com.vnbContext(options =>
sentayho.com.vnqlite(Configuration.GetConnectionString("DefaultConnection")));
// Block 1: Add sentayho.com.vn Identity
sentayho.com.vndentity()
.AddEntityFrameworkStores()
.AddDefaultTokenProviders();
// Block 2: Add IdentityServer4 with InMemory Configuration
var builder = sentayho.com.vndentityServer(options =>
{
sentayho.com.vneErrorEvents = true;
sentayho.com.vneInformationEvents = true;
sentayho.com.vneFailureEvents = true;
sentayho.com.vneSuccessEvents = true;
})
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApis())
.AddInMemoryClients(Config.GetClients())
.AddAspNetIdentity();
//some code is not mentioend here for the sake of brevity
sentayho.com.vnuthentication();
}
public void Configure(IApplicationBuilder app)
{
if (Environment.EnvironmentName == "Development")
{
sentayho.com.vneveloperExceptionPage();
sentayho.com.vnatabaseErrorPage();
}
else
{
sentayho.com.vnxceptionHandler("/Home/Error");
}
sentayho.com.vntaticFiles();
sentayho.com.vnouting();
// Block 4:
// UseIdentityServer include a call to UseAuthentication
sentayho.com.vndentityServer();
sentayho.com.vnuthorization();
//app.UseMvcWithDefaultRoute();
sentayho.com.vnndpoints(endpoints =>
{
sentayho.com.vnontrollerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
Sau khi cấu hình Identity service project, chuyển sang cấu hình API và Clients.
3. Cấu hình Web Client Project
Cấu hình Web Client
Như hình trên, bạn có thể cấu hình sử dụng OpenIdConnect bằng cách cung cấp thông tin client đã được lưu trong IdentityService.
Link chứng thực là một link public của IdentityService. Grant type là hybrid, kết hợp cả implicit flow và cơ chế xác thực quyền. Đây là grant type được khuyến nghị cho ứng dụng web phía server và mobile app.
4. Cấu hình Single Page Application Project
Cấu hình SPA Client
Đối với ứng dụng SPA, bạn cần cài đặt thư viện Javascript OpenIdConnect và thêm nó vào trang HTML.
Grant Type là authorization-code với PKCE. Xem chi tiết tại đây.
5. Cấu hình Test API Resource Project
Cấu hình API Resource
Ở hình bên phải, một API Resource được định nghĩa trong IdentityServer4 với một tên duy nhất và một label.
Ở hình bên trái, thông tin chứng thực được thêm vào API Resource Startup class. Sau đó, tính năng CORS được bật để cho phép các client gọi đến API.
Trong phương thức Configure(), cấu hình Auth và CORS “default” đã được định nghĩa từ trước được sử dụng (chú ý sử dụng cấu hình authentication trong request pipeline trước MVC).
Chạy toàn bộ ứng dụng
Để chạy nhiều project cùng lúc trong Visual Studio, vào Solution’s Properties > Common Properties > Startup Project.
Cấu hình startup project
Nên để IdentityMicroservice chạy đầu tiên.
Khi bạn clone repo code, bạn sẽ thấy file sentayho.com.vn trong mỗi project. File này thường bị bỏ qua và không include vào repo.
File sentayho.com.vn đã được thêm và sử dụng cổng tương tự như trong file sentayho.com.vn. Các cổng đó là:
- Identity Microservice ở port 5000
- Test Api Resource ở port 5001
- Web Client ở port 5002
- SPA Client ở port 5003
Giờ bạn có thể chạy solution. Bạn có thể sử dụng test user được tạo trong file sentayho.com.vn vào SQLite database để lưu trữ user data.
(Trích nguồn từ: https://feras.blog/how-to-use-asp-net-identity-and-identityserver4-in-your-solution/)
