Trong bài viết này, mình sẽ hướng dẫn các bạn làm quen với thư viện Identity Server 4, và tích hợp các service In-Memory của Identity Server 4 vào Project Web API trong .NET Core.
Hiện tại, mình chỉ biết 1 vài thư viện làm nhiệm vụ như Authorization Server:
Mình đã thử sử dụng .Net Core 2.0 Preview, thì thấy code khác rất nhiều, cả về SDK lẫn các hàm trong IdentityServer 4.
Trong ví dụ dưới dây, mình sẽ chọn Project Web API, vì template project đã có khai báo 1 số thư viện, hàm sẵn, không cần thêm lại như Empty Project.
Port sử dụng là 60361. Đây là project xây dựng Authorization Server.
Mặc định, Project Web API sẽ không có Authentication cho project Web API.
Để đơn giản, chúng ta sẽ sử dụng đối tượng trên Memory thay vì sử dụng chúng trên database
Trang này để lấy thông tin metadata của IdentityServer: scope, issuer name, key material, ..
Đối với trường hợp bạn dùng grant_type=password, thì contype-header phải là application/x-www-form-urlencoded.
Trường hợp bạn dùng Fiddler:
Content-type: application/x-www-form-urlencoded
RequestBody:
client_id=oauthClient&client_secret=superSecretPassword&grant_type=password&username=anbinhtrong&password=password123&scope=customAPI.read
Nếu request thành công, bạn sẽ nhận về được chuỗi token giống như sau:
Download example: MediaFire
Identity Server 4 Sample: https://github.com/IdentityServer/IdentityServer4.Samples
Chúc các bạn thành công!
Identity Server 4 là gì?
IdentityServer4 là 1 framework .NET dành cho OpenID Connect và OAuth 2.0. Ngoài ra, bạn có thể tìm 1 số thư viện khác dành cho .net core.Hiện tại, mình chỉ biết 1 vài thư viện làm nhiệm vụ như Authorization Server:
- Identity Server 4
- Azure Active Directory
- Auth0
- OpenIddict
- Google OAuth 2.0
- Facebook Login
- …
Mình đã thử sử dụng .Net Core 2.0 Preview, thì thấy code khác rất nhiều, cả về SDK lẫn các hàm trong IdentityServer 4.
Khai báo Identity Server 4
Tạo Project .NET Core mới, chọn Empty/Web API. Mình khuyến khích các bạn chọn Empty Project vì chúng ta dùng host này để tạo access token, validate token, … Còn 1 số api khác sẽ được viết trong Project Web API.Trong ví dụ dưới dây, mình sẽ chọn Project Web API, vì template project đã có khai báo 1 số thư viện, hàm sẵn, không cần thêm lại như Empty Project.
Port sử dụng là 60361. Đây là project xây dựng Authorization Server.
Mặc định, Project Web API sẽ không có Authentication cho project Web API.
Cài đặt Identiy Server 4
Install-Package IdentityServer4
Trong file Startup.cs, bạn đăng ký dependency cho IdentityServer4 trong hàm ConfigureServices và sử dụng nó trong hàm Configure
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentityServer()
.AddInMemoryClients(new List<Client>())
.AddInMemoryIdentityResources(new List<IdentityResource>())
.AddInMemoryApiResources(new List<ApiResource>())
.AddTestUsers(new List<TestUser>())
.AddTemporarySigningCredential();
// Add framework services.
//…
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//log factory
app.UseIdentityServer();
app.UseStatusCodePages();
//another code here
}
Sau khi cấu hình xong, các bạn có thể xem OpenID Connect Discovery Document tại: /.well-known/openid-configurationĐịnh nghĩa Clients, Resources, và Users
Đầu tiên chúng ta cần lưu trữ các ứng dụng Client được phép sử dụng IdentityServer, Resource, và User cho phép xác thực chúng.Để đơn giản, chúng ta sẽ sử dụng đối tượng trên Memory thay vì sử dụng chúng trên database
internal class Clients
{
public static IEnumerable<Client> Get()
{
return new List<Client> {
new Client {
ClientId = "oauthClient",
ClientName = "Example Client Credentials Client Application",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets = new List<Secret> {
new Secret("superSecretPassword".Sha256())},
AllowedScopes = new List<string> {"customAPI.read"}
}
};
}
}
internal class Resources
{
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource> {
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Email(),
new IdentityResource {
Name = "role",
UserClaims = new List<string> {"role"}
}
};
}
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource> {
new ApiResource {
Name = "customAPI",
DisplayName = "Custom API",
Description = "Custom API Access",
UserClaims = new List<string> {"role"},
ApiSecrets = new List<Secret> {new Secret("scopeSecret".Sha256())},
Scopes = new List<Scope> {
new Scope("customAPI.read"),
new Scope("customAPI.write")
}
}
};
}
}
internal class Users
{
public static List<TestUser> Get()
{
return new List<TestUser> {
new TestUser {
SubjectId = "5BE86359-073C-434B-AD2D-A3932222DABE",
Username = "anbinhtrong",
Password = "password123",
Claims = new List<Claim> {
new Claim(JwtClaimTypes.Email, "anbinhtrong@gmail.com"),
new Claim(JwtClaimTypes.Role, "admin")
}
}
};
}
}
Cập nhật lại file Startup.cs
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//add Identity Server
services.AddIdentityServer()
.AddInMemoryClients(Clients.Get())
.AddInMemoryIdentityResources(Configurations.Resources.GetIdentityResources())
.AddInMemoryApiResources(Configurations.Resources.GetApiResources())
.AddTestUsers(Users.Get())
.AddTemporarySigningCredential();
// Add framework services.
services.AddMvc();
}
Sau khi cài đặt xong, bạn mở trình duyệt gõ địa chỉ: http://localhost:60361/.well-known/openid-configurationTrang này để lấy thông tin metadata của IdentityServer: scope, issuer name, key material, ..
Test IdentityServer 4
Bạn dùng PostMan hoặc Fiddler để đăng nhập lấy token.Đối với trường hợp bạn dùng grant_type=password, thì contype-header phải là application/x-www-form-urlencoded.
Trường hợp bạn dùng Fiddler:
RequestBody:
client_id=oauthClient&client_secret=superSecretPassword&grant_type=password&username=anbinhtrong&password=password123&scope=customAPI.read
Nếu request thành công, bạn sẽ nhận về được chuỗi token giống như sau:
Download example: MediaFire
Tham khảo
https://www.scottbrady91.com/Identity-Server/Getting-Started-with-IdentityServer-4Identity Server 4 Sample: https://github.com/IdentityServer/IdentityServer4.Samples
Chúc các bạn thành công!
Nhatkyhoctap's blog
OAuth2 có 4 loại grant type:
Trả lờiXóa- Resource Owner Password Credentials
- Authorization Code
- Implicit
- Client Credentials
The Password grant type is a way to exchange a user's credentials for an access token.
Khi nào thì sử dụng grant này?
Chỉ nên sử dụng cho những ứng dụng thực sự được tin tưởng vì nó trực tiếp xử lý thông tin đăng nhập của người dùng.
The flow includes the following steps:
Ứng dụng đưa ra một form cho phép người dùng nhập thông tin đăng nhập (ví dụ: username/password).
Ứng dụng gửi thông tin đăng nhập cùng thông tin định danh của mình lên authorization server. Authorization server xác thực thông tin, trả lại access token và refresh token (nếu có).
Ứng dụng sử dụng access token truy cập tài nguyên trên resource server.
Update
Trả lờiXóaIdentity Server 4: Add new scope when you want to registering ID4
https://docs.identityserver.io/en/latest/reference/api_scope.html
https://techmaster.vn/posts/33959/khai-niem-ve-json-web-token
Trả lờiXóaPhần payload giảng rất rõ về issue
As it turns out, my suspicions were right. The audience aud claim in a JWT is meant to refer to the Resource Servers that should accept the token.
Trả lờiXóaAs this post simply puts it:
The audience of a token is the intended recipient of the token.
The audience value is a string -- typically, the base address of the resource being accessed, such as https://contoso.com.
The client_id in OAuth refers to the client application that will be requesting resources from the Resource Server.
The Client app (e.g. your iOS app) will request a JWT from your Authentication Server. In doing so, it passes it's client_id and client_secret along with any user credentials that may be required. The Authorization Server validates the client using the client_id and client_secret and returns a JWT.
The JWT will contain an aud claim that specifies which Resource Servers the JWT is valid for. If the aud contains www.myfunwebapp.com, but the client app tries to use the JWT on www.supersecretwebapp.com, then access will be denied because that Resource Server will see that the JWT was not meant for it.