Tìm hiểu về IdentityServer 4

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.

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:
  1. Identity Server 4
  2. Azure Active Directory
  3. Auth0
  4. OpenIddict
  5. Google OAuth 2.0
  6. Facebook Login
Trước khi bắt đầu, các bạn cần đảm bảo đang sử dụng Visual Studio 2017, .Net Core 1.1.
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-configuration

Trang 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:




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

Tham khảo

https://www.scottbrady91.com/Identity-Server/Getting-Started-with-IdentityServer-4
Identity Server 4 Sample: https://github.com/IdentityServer/IdentityServer4.Samples

Chúc các bạn thành công! 
Nhatkyhoctap's blog