نحوه استفاده از Identity Server 4 با ASP.NET Core 2.0

در این مقاله می خواهیم درباره ی Identity Server 4 با ASP.NET Core 2.0 صحبت کنیم از این رو روی سه پروژه ی اصلی کار می کنیم و کد های هر قسمت را با تو ضیحات مربوط به آن در اختیار شما قرار می دهیم.

نحوه استفاده از Identity Server 4 با ASP.NET Core 2.0

 مساله

چگونه از Identity Server 4 با  ASP.NET Core 2.0 استفاده کنیم؟

راه حل

در اینجا فرض کرده ایم که شما اطلاعات پایه ای درباره ی Identity Server دارید برای اطلاعات بیشتر به مستندات اینجا مراجعه کنید.

من اینجا سه پروژه را پیاده سازی خواهم کرد:

Server - که روی پورت 5000 اجرا می شود.

API (یعنی منابع محافظت شده) - که روی پورت 5001 اجرا می شود.

Client - که روی پورت 5002 اجرا می شود.

Auth. Server

یک وب اپلیکیشن خالی بسازید و Quickstart ، View ها و پوشه ی wwwroot را از GitHub کپی کنید. یک کلاس Startup بسازید.

public class Startup  
 {  
     public void ConfigureServices(  
         IServiceCollection services)  
     {  
         services.AddMvc();  
         services.AddIdentityServer()  
                     .AddDeveloperSigningCredential(filename: "tempkey.rsa")  
                     .AddInMemoryApiResources(Config.GetApiResources())  
                     .AddInMemoryIdentityResources(Config.GetIdentityResources())  
                     .AddInMemoryClients(Config.GetClients())  
                     .AddTestUsers(Config.GetUsers());  
     }  
  
     public void Configure(  
         IApplicationBuilder app,   
         IHostingEnvironment envloggerFactory)  
     {  
         app.UseIdentityServer();  
         app.UseStaticFiles();  
         app.UseMvcWithDefaultRoute();  
     }  
 } 

یک کلاس Config(پیکربندی) بسازید و متد ها را برای گرفتن API ، ،کلاینت ها و کاربران و اهراز هویت را اضافه کنید.

public static class Config  
 {  
     public static IEnumerable<ApiResource> GetApiResources()  
     {  
         return new List<ApiResource>  
         {  
             new ApiResource("fiver_auth_api", "Fiver.Security.AuthServer.Api")  
         };  
     }  
  
     public static IEnumerable<IdentityResource> GetIdentityResources()  
     {  
         return new List<IdentityResource>  
         {  
             new IdentityResources.OpenId(),  
             new IdentityResources.Profile(),  
         };  
     }  
  
     public static IEnumerable<Client> GetClients()  
     {  
         return new List<Client>  
         {  
             new Client  
             {  
                 ClientId = "fiver_auth_client",  
                 ClientName = "Fiver.Security.AuthServer.Client",  
                 ClientSecrets = { new Secret("secret".Sha256()) },  
  
                 AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,  
                 AllowOfflineAccess = true,  
                 RequireConsent = false,  
  
                 RedirectUris = { "http://localhost:5002/signin-oidc" },  
                 PostLogoutRedirectUris =   
                   { "http://localhost:5002/signout-callback-oidc" },  
                   
                 AllowedScopes =  
                 {  
                     IdentityServerConstants.StandardScopes.OpenId,  
                     IdentityServerConstants.StandardScopes.Profile,  
                     "fiver_auth_api"  
                 },  
             }  
         };  
     }  
  
     public static List<TestUser> GetUsers()  
     {  
         return new List<TestUser>  
         {  
             new TestUser  
             {  
                 SubjectId = "1",  
                 Username = "james",  
                 Password = "password",  
                 Claims = new List<Claim>  
                 {  
                     new Claim("name", "James Bond"),  
                     new Claim("website", "https://james.com")  
                 }  
             }  
         };  
     }  
 } 

API

یک پروژه ی API بسازید و کلاس Startup آن را به روزرسانی کنید.

public class Startup  
  {  
      public void ConfigureServices(  
          IServiceCollection services)  
      {  
          services.AddAuthentication(  
             IdentityServerAuthenticationDefaults.JwtAuthenticationScheme)  
                  .AddIdentityServerAuthentication(options =>  
                   {  
                       options.Authority = "http://localhost:5000"; // Auth Server  
                       options.RequireHttpsMetadata = false; // only for development  
                       options.ApiName = "fiver_auth_api"; // API Resource Id  
                   });  
  
          services.AddMvc();  
      }  
  
      public void Configure(  
          IApplicationBuilder app,   
          IHostingEnvironment env)  
      {  
          app.UseAuthentication();  
          app.UseMvcWithDefaultRoute();  
      }  
  } 

یک Controller بسازید و با استفاده از ویژگی [Authorize] از آن محافظت کنید.

[Authorize]  
 [Route("movies")]  
 public class MoviesController : Controller  
 { 

Client

یک وب اپلیکیشن بسازید و کلاس Startup آن را به روز رسانی کنید.

public class Startup  
 {  
     public void ConfigureServices(  
         IServiceCollection services)  
     {  
         JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();  
  
         services.AddAuthentication(options =>  
         {  
             options.DefaultScheme =   
                 CookieAuthenticationDefaults.AuthenticationScheme;  
             options.DefaultChallengeScheme =   
                 OpenIdConnectDefaults.AuthenticationScheme;  
         })  
         .AddCookie()  
         .AddOpenIdConnect(options =>  
         {  
             options.SignInScheme =   
                 CookieAuthenticationDefaults.AuthenticationScheme;  
             options.Authority = "http://localhost:5000"; // Auth Server  
             options.RequireHttpsMetadata = false; // only for development   
             options.ClientId = "fiver_auth_client"; // client setup in Auth Server  
             options.ClientSecret = "secret";  
             options.ResponseType = "code id_token"; // means Hybrid flow  
             options.Scope.Add("fiver_auth_api");  
             options.Scope.Add("offline_access");  
             options.GetClaimsFromUserInfoEndpoint = true;  
             options.SaveTokens = true;  
         });  
  
         services.AddMvc();  
     }  
  
     public void Configure(  
         IApplicationBuilder app,   
         IHostingEnvironment env)  
     {  
         app.UseAuthentication();  
         app.UseMvcWithDefaultRoute();  
     }  
 }  

یک Controller برای دسترسی به API ها اضافه کنید.

[Authorize]  
  public class HomeController : Controller  
  {  
      [AllowAnonymous]  
      public IActionResult Index()  
      {  
          return View();  
      }  
  
      public async Task<IActionResult> Movies()  
      {  
          var accessToken = await HttpContext.GetTokenAsync("access_token");  
  
          var client = new HttpClient();  
          client.DefaultRequestHeaders.Authorization = new   
              AuthenticationHeaderValue("Bearer", accessToken);  
          var content = await client.GetStringAsync("http://localhost:5001/movies");  
  
          var model = JsonConvert.DeserializeObject<List<MovieViewModel>>(content);  
            
          return View(model);  
      }  
  
      public async Task Logout()  
      {  
          await HttpContext.SignOutAsync(  
             CookieAuthenticationDefaults.AuthenticationScheme);  
          await HttpContext.SignOutAsync(  
              OpenIdConnectDefaults.AuthenticationScheme);  
      }  
  } 

توجه

می توانید source code را از مخزن GitHub دانلود کنید.

بحث

وب سایت IdentityServer4 ، IdentityServer4 را به عنوان یک فریم ورک  OpenID Connect و OAuth 2.0 برای ASP.NET Core معرفی می کند که ویژگی های زیر را برای شما فعال می کند:

-تمرکز روی منطق ورود به اپیکیشن شما.

-تک ثبت نامی بودن

-مسائل دسترسی به token ها برای API ها

Gateway- برای ارائه دهندگان هویت سنجی اضافه نظیر گوگل، Facebook و غیره

-قابلیت شخصی سازی

در اینجا من بطور مختصر درباره ی OAuth 2.0 و OpenID Connect بحث خواهم کرد اما برای اطلاعات بیشتر و عمیق تر درباره ی OAuth 2.0 و OpenID Connect دوره های آنلاین و پست های نوشته شده توسط توسعه دهنده ی Identity Server ، Dominick Baier ، را پیشنهاد می کنم.

(OAuth 2 Flows) جریان کاری OAuth 2

OAuth 2 جریان های مختلف یا انواع کمک ها را برای انواع مختلفی از موارد استفاده ارائه می دهد. من شخصا این موارد را به دو دسته ی اصلی تقسیم بندی می کنم: جریان هایی که نیاز به مجوز برای تعامل کاربر با سرور دارند و جریان هایی که نیاز ندارند. اجازه دهید در ابتدا مواردی را که هنگام بحث درباره ی موارد زیر به آن ها نیاز داریم را تعریف کنیم:

تعاریف

کاربر - فردی است که از یک کلاینت استفاده می کند و مالک منابع حفاظت شده است.

کلاینت - اپلیکیشنی است که نیاز به دسترسی به منابع محافظت شده را دارد.

منابع حفاظت شده - منابعی که از دسترسی های غیر مجاز محافظت می شوند. (به عنوان مثال Web API)

سرور - سرور به کاربر مجوز می دهد و Access Token ها را باز می گرداند.

Access Token - یک کلید مخفی برای دسترسی به منابع حفاظت شده می باشد.

Scope ها - مقادیری که بر اساس آن دسترسی به ویژگی های حفاظت شده محدود می شود.

Redirect URI - محلی است که کاربر پس از اینکه  Auth. Server مجوزدهی را تکمیل می کند به آن بازمی گردد.

Client ID - شناسه ی مشتری است که توسط Auth. Server ثبت شده است.

Client Secret - رمز کلاینت می باشد که توسط Auth. Server ثبت شده است و باید به صورت محرمانه نگهداری شود.

تعاملات مورد نیاز کاربر با Auth. Server

Implicit Grant

موارد زیر معمولا کلاینت های بومی/ محلی/ موبایل استفاده می شود و گام های زیر را دارد:

-کاربر به کلاینت دسترسی دارد.

-کاربر به Auth. Server هدایت می شود.

-کاربر نام کاربری/رمزعبور را ارائه می دهد.

-کاربر به کلاینت با یک Access Token بازگردانده می شود.

توجه

Access Token در اختیار کاربر قرار می گیرد.

کاربر با استفاده از Access Token به منابع حفاظت شده دسترسی می یابد.

توجه

توصیه می شود که از Authorisation Code به جای Implicit Grant استفاده کنید.

Authorisation Code

موارد زیر معمولا برای کلاینت های وب اپلیکیشن استفاده می شود و گام های زیر را دارد.

-کاربر به کلاینت دسترسی دارد.

-کاربر به Auth. Server فرستاده می شود.

-کاربر نام کاربری/ رمزعبور را ارائه می دهد.

-کاربر با یک کد به کلاینت بازگردانده می شود.

توجه

کد در اختیار کاربر قرار می گیرد.

-کاربر به Auth. Server برای تغییر کد با یک Access Token دسترسی دارد.

توجه

Access Token در اختیار کاربر قرار نمی گیرد.

-کلاینت به منابع حفاظت شده با استفاده از Access Token دسترسی دارد.

نیاز به تعاملات کاربر با Auth. Server نیست

گواهی نامه رمزعبور مالک منابع

موارد زیر معمولا برای کلاینت های مورداعتماد استفاده می شود و گام های زیر را دارد:

-کاربر به کلاینت دسترسی پیدا می کند و نام کاربری/رمزعبر را ارائه می دهد.

توجه

نام کاربری / رمزعبور در اختیار کاربر قرار می گیرد

-کلاینت برای تغییر نام کاربری / رمزعبور با یک Access Token دسترسی پیدا می کند.

-کلاینت با استفاده از Access Token به منابع محافظت شده دسترسی پیدا می کند.

مجوز های کلاینت

موارد زیر معمولا برای ارتباطات client-server بدون مداخله ی بشر استفاده می شود و شامل گام های زیر است:

-کلاینت برای تغییر Client ID و رمز با یک Access Token به Auth. Server دسترسی پیدا می کند.

-کلاینت با استفاده از Access Token به منابع محافظت شده دسترسی پیدا می کند.

OpenID Connect

OpenID Connect یک لایه روی OAuth 2.0 است و از مطالبات برای انتقال اطلاعات در مورد کاربران استفاده می کند و سرویس هایی برای بازبینی شناسه ی کاربر و دسترسی به اطلاعات پروفایل آن ها ارائه می دهد.

OpenID Connect از جریان های کاری OAuth 2.0 برای دستیابی به Identity Token که مواردی نظیر شناسه  کاربر را (به عنوان یک زیرمجموعه) ، صدور مجوز (به عنوان iss )، کلاینت (به صورت صوتی) و تاریخ های صدور/انقضا را می دهد، استفاده میکند . این tokenها به فرمتJWT  و بر مبنای رشته های ۶۴ تایی است.

سورس کد GitHub