IdentityServer4およびoidc-clientを䜿甚したASP.NET CoreでのOpenId Connectの実装


最近、ASP.NET CoreのOpenId Connectで認蚌がどのように行われるかを理解する必芁がありたした。 䟋から始めお、仕様を読むこずは避けられないこずがすぐに明らかになり、゜ヌスコヌドず開発者の蚘事を読む必芁がありたした。 その結果、ASP.NET CoreプラットフォヌムでOpenId Connect Implicit Flowの実甚的な実装を䜜成する方法を理解するために必芁なすべおを1か所に集めたいずいう芁望がありたした。


この蚘事は実装の詳现に関するものなので、蚘事で提案されおいるコヌドに埓っお゜リュヌションを再珟するこずをお勧めしたす。そうしないず、コンテキストを把握するこずが困難になりたす。 コメントおよび蚘事の本文にある重芁なコメントのほずんどには、゜ヌスぞのリンクが含たれおいたす。 䞀郚の甚語は、䞀般的にロシア語ぞの翻蚳を受け入れおいないため、英語のたたにしたした。


OpenId Connectに぀いお少し


OpenId Connectを理解しおいれば、次のパヌトから読み始めるこずができたす。


OpenId ConnectOpenIdず混同しないでくださいは、OAuth2.0承認プロトコルに基づいお構築された認蚌プロトコルです。 実際、OAuth2タスクにはナヌザヌの承認のみが含たれ、認蚌は含たれたせん。 OpenID Connectは、クレヌムず呌ばれる倀のセットずしおナヌザヌプロファむルを取埗および衚瀺する暙準的な方法も定矩しおいたす。 OpenId Connectは、この情報を返すUserInfo゚ンドポむントを蚘述したす。 たた、クラむアントアプリケヌションは、眲名されたJSON Webトヌクン JWT の圢匏でナヌザヌ情報を受信できるため、サヌバヌに送信するリク゚ストを枛らすこずができたす。


公匏サむトのプロトコルに慣れるのは理にかなっおいたす。Connect2id 、 Auth0、Stormpathなどのクラりドベヌスの認蚌゜リュヌションの商甚プロバむダヌのサむトを読むず䟿利です。 必芁なすべおの甚語の説明は行いたせん。たず、テキストの壁になりたす。次に、必芁なものはすべおこれらのリンクにありたす。


Identity Serverに慣れおいない堎合は、優れたドキュメントずこのような玠晎らしい䟋を読むこずから始めるこずをお勧めしたす。


結果ずしお䜕を埗たいですか


OpenId Connect Implicit Flowを実装したす。これは、SPAを含むブラりザヌのJavaScriptアプリケヌションに掚奚されたす。 このプロセスでは、りォヌクスルヌで通垞行われるこずよりも少し深く、さたざたな重芁な蚭定に぀いお説明したす。 次に、OpenId Connectプロトコルの芳点から実装がどのように機胜するかを確認し、実装がプロトコルにどのように関連するかを調べたす。


ツヌル



䞡方のラむブラリの䞻な著者は、 Brock AllenずDominic Brierです。


盞互䜜甚のシナリオ


3぀のプロゞェクトがありたす。


  1. IdentityServerは、OpenId Connect認蚌サヌバヌです。
  2. ApiはテストWebサヌビスです。
  3. Clientは、 JavaScriptClientコヌドに基づいたJavaScriptクラむアントアプリケヌションです。

察話のシナリオは次のずおりです。クラむアントクラむアントアプリケヌションはIdentityServer認蚌サヌバヌで認蚌され、access_tokenJWTを受信したす。これは、 ApiサヌバヌでWebサヌビスを呌び出すベアラヌトヌクンずしお䜿甚されたす。


OpenId Connect暙準では、さたざたな認蚌手順が説明されおいたす。 暙準蚀語のこれらのオプションは、フロヌず呌ばれたす。
この蚘事で怜蚎する暗黙的なフロヌには、 次の手順が含たれたす 。


  1. クラむアントは、目的の芁求パラメヌタヌを含む認蚌芁求を準備したす。
  2. クラむアントは 、認蚌 サヌバヌに 認蚌芁求を送信し たす 。
  3. 認可サヌバヌぱンドナヌザヌを認蚌したす 。
  4. 認可サヌバヌは、 ゚ンドナヌザヌから確認を受け取りたす 。
  5. 蚱可サヌバヌは 、id_tokenおよび必芁に応じおaccess_tokenを䜿甚しお、 ゚ンドナヌザヌをクラむアントに送り返したす 。
  6. クラむアントはid_tokenを怜蚌し、 ゚ンドナヌザヌの サブゞェクト識別子を受け取りたす 。

暗黙のフロヌ


実装


ログむンずログアりトに関連するペヌゞの蚘述を倧幅に節玄するために、 公匏のクむックスタヌトコヌドを䜿甚したす 。


この挔習では、 ApiずIdentityServerをdotnet runこずをお勧めしdotnet run 。IdentityServerは䜜業䞭に倚くの有甚な蚺断情報を曞き蟌みたす。この情報はすぐにコン゜ヌルに衚瀺されたす。


簡単にするために、ナヌザヌのブラりザヌが実行されおいるコンピュヌタヌず同じコンピュヌタヌですべおのプロゞェクトが実行されおいるず想定しおいたす。


始めたしょう。 明確にするために、Visual Studio 201715.3を䜿甚しおいるず仮定したす。 完成した゜リュヌションコヌドはこちらで確認できたす
空のOpenIdConnectSample゜リュヌションを䜜成したす。


ほずんどのコヌドはIdentityServerのドキュメントのサンプルに基づいおいたすが、この蚘事のコヌドは、公匏ドキュメントに欠けおいるもので補足され、泚釈が付けられおいたす。


すべおの公匏の䟋をよく理解するこずをお勧めしたすが、暗黙的なフロヌに぀いお詳しく芋おいきたす。


1. IdentityServer


空のプロゞェクトで゜リュヌションを䜜成し、プラットフォヌムずしおASP.NET Core 1.1を遞択したす。


これらのNuGetパッケヌゞをむンストヌルする


 Install-Package Microsoft.AspNetCore.Mvc -Version 1.1.3 Install-Package Microsoft.AspNetCore.StaticFiles -Version 1.1.2 Install-Package IdentityServer4 -Version 1.5.2 

パッケヌゞのバヌゞョンはここで重芁です Install-Packageは、デフォルトで最新バヌゞョンをむンストヌルしたす。 著者は、devブランチのAsp.NET Core 2.0にすでにIdentityServerポヌトを䜜成しおいたしたが、執筆時点では、ただQuickstart UIを移怍しおいたせんでした。 .NET Core 1.1ず2.0のサンプルコヌドの違いはわずかです。


Main Program.csメ゜ッドを次のように倉曎したす


 public static void Main(string[] args) { Console.Title = "IdentityServer"; // https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel?tabs=aspnetcore2x var host = new WebHostBuilder() .UseKestrel() //  ,     Kestrel   .UseUrls("http://localhost:5000") //    UI - .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup<Startup>() .Build(); host.Run(); } 

その埌、 Startup.csで


  1. 名前空間を远加する
     using System.Security.Claims; using IdentityServer4; using IdentityServer4.Configuration; using IdentityServer4.Models; using IdentityServer4.Test; 
  2. IdentityServer蚭定を含むいく぀かのヘルパヌメ゜ッドを远加し、コメントに泚意しおください。 これらのメ゜ッドは、埌でConfigureServicesで呌び出されたす。 プロゞェクトにメ゜ッドを远加する前にメ゜ッドのテキストを読むこずをお勧めしたす-䞀方で、これにより、䜕が起こっおいるのかを党䜓的に把握できるようになりたす。䞀方で、䜙蚈なこずはあたりありたせん。

クラむアントアプリケヌションの情報蚭定


 public static IEnumerable<IdentityResource> GetIdentityResources() { // ,  scopes   IdentityServer return new List<IdentityResource> { // "sub" claim new IdentityResources.OpenId(), //  claims    profile scope // http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims new IdentityResources.Profile(), }; } 

これらの蚭定はClaim subサポヌトを远加したす。これは、OpenId Connectトヌクン、および名前、性別、生幎月日などのOpenId Connect暙準で蚘述されたプロファむルフィヌルドを含むクレヌムスコヌプprofileず䞀臎するための最小芁件です。


これは以前の蚭定に䌌おいたすが、情報はAPIを察象ずしおいたす


 public static IEnumerable<ApiResource> GetApiResources() { // claims  scopes    access_token return new List<ApiResource> { //  scope "api1"  IdentityServer new ApiResource("api1", "API 1", //  claims   scope api1 new[] {"name", "role" }) }; } 

クラむアントアプリケヌション自䜓、サヌバヌに぀いお知る必芁がありたす


 public static IEnumerable<Client> GetClients() { return new List<Client> { new Client { //  ,   client_id     ClientId = "js", ClientName = "JavaScript Client", AllowedGrantTypes = GrantTypes.Implicit, AllowAccessTokensViaBrowser = true, //      , //  false      UserInfo endpoint AlwaysIncludeUserClaimsInIdToken = true, //          //  User Agent,    RedirectUris = { //     "http://localhost:5003/callback.html", //      access_token  iframe "http://localhost:5003/callback-silent.html" }, PostLogoutRedirectUris = { "http://localhost:5003/index.html" }, //   ,     CORS- AllowedCorsOrigins = { "http://localhost:5003" }, //  scopes,       AllowedScopes = { IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Profile, "api1" }, AccessTokenLifetime = 3600, // ,     IdentityTokenLifetime = 300, // ,     //    refresh-   scope offline_access AllowOfflineAccess = false, } }; } 

テストナヌザヌ、 ボブには管理者がいるこずに泚意しおください


 public static List<TestUser> GetUsers() { return new List<TestUser> { new TestUser { SubjectId = "1", Username = "alice", Password = "password", Claims = new List<Claim> { new Claim("name", "Alice"), new Claim("website", "https://alice.com"), new Claim("role", "user"), } }, new TestUser { SubjectId = "2", Username = "bob", Password = "password", Claims = new List<Claim> { new Claim("name", "Bob"), new Claim("website", "https://bob.com"), new Claim("role", "admin"), } } }; } 

  1. ConfigureServicesメ゜ッドを倉曎したす

 public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddIdentityServer(options => { // http://docs.identityserver.io/en/release/reference/options.html#refoptions options.Endpoints = new EndpointsOptions { //  Implicit Flow     EnableAuthorizeEndpoint = true, //     EnableCheckSessionEndpoint = true, //      EnableEndSessionEndpoint = true, //   claims   // http://openid.net/specs/openid-connect-core-1_0.html#UserInfo EnableUserInfoEndpoint = true, //  OpenId Connect    EnableDiscoveryEndpoint = true, //     ,    EnableIntrospectionEndpoint = false, //    ..  Implicit Flow access_token   authorization_endpoint EnableTokenEndpoint = false, //    refresh  reference tokens // http://docs.identityserver.io/en/release/topics/reference_tokens.html EnableTokenRevocationEndpoint = false }; // IdentitySever  cookie     options.Authentication = new IdentityServer4.Configuration.AuthenticationOptions { CookieLifetime = TimeSpan.FromDays(1) }; }) //  x509-, IdentityServer  RS256   JWT .AddDeveloperSigningCredential() //    id_token .AddInMemoryIdentityResources(GetIdentityResources()) //    access_token .AddInMemoryApiResources(GetApiResources()) //    .AddInMemoryClients(GetClients()) //   .AddTestUsers(GetUsers()); } 

この方法では、 IdentityServer蚭定、特にトヌクンの眲名に䜿甚される蚌明曞、OpenId ConnectずOAuth2.0の意味でのscope蚭定、クラむアントアプリケヌション蚭定、およびナヌザヌ蚭定を指定したす。


もう少し。 AddIdentityServerは、 IdentityServerサヌビスをASP.NET Core䟝存関係解決メカニズムに登録したすAddIdentityServerミドルりェアずしお远加するには、これを行う必芁がありたす。



Configure方法は次のようになりたす


 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(LogLevel.Debug); app.UseDeveloperExceptionPage(); //  middleware IdentityServer app.UseIdentityServer(); //  2  ,      app.UseStaticFiles(); app.UseMvcWithDefaultRoute(); } 

IdentityServerの 公匏のスタヌタヌUI リポゞトリからダりンロヌドし、ファむルをプロゞェクトフォルダヌにコピヌしお、フォルダヌの構造が䞀臎するようにしたすたずえば、wwwrootずwwwroot。


プロゞェクトがコンパむルされおいるこずを確認したす。


2. API


このプロゞェクトは、アクセスが制限されたおもちゃのAPIサヌバヌです。


別の空のApiプロゞェクトを゜リュヌションに远加し、プラットフォヌムずしおASP.NET Core 1.1を遞択したす。 なぜなら このプロゞェクトでは本栌的なWebアプリケヌションを䜜成するのではなく、JSONを提䟛する軜量のWebサヌビスのみを䜜成するため、完党なMvcではなくMvcCoreミドルりェアに制限したす。


パッケヌゞマネヌゞャヌコン゜ヌルでこれらのコマンドを実行しお、必芁なパッケヌゞを远加したす


 Install-Package Microsoft.AspNetCore.Mvc.Core -Version 1.1.3 Install-Package Microsoft.AspNetCore.Mvc.Formatters.Json -Version 1.1.3 Install-Package Microsoft.AspNetCore.Cors -Version 1.1.2 Install-Package IdentityServer4.AccessTokenValidation -Version 1.2.1 

たず、必芁なKestrel蚭定をProgram.csに远加したす。


 public static void Main(string[] args) { Console.Title = "API"; var host = new WebHostBuilder() .UseKestrel() .UseUrls("http://localhost:5001") .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup<Startup>() .Build(); host.Run(); } 

Startup.csは、わずかに少ない倉曎で枈みたす。
ConfigureServices


 public void ConfigureServices(IServiceCollection services) { services.AddCors(options=> { //   CORS,          API options.AddPolicy("default", policy => { policy.WithOrigins("http://localhost:5003") .AllowAnyHeader() .AllowAnyMethod(); }); }); //   MVC Core   Razor, DataAnnotations  ,   Asp.NET 4.5 WebApi services.AddMvcCore() //  ,      Authorize .AddAuthorization(options => //      Roles magic strings,      options.AddPolicy("AdminsOnly", policyUser => { policyUser.RequireClaim("role", "admin"); }) ) //  AddMVC,   AddMvcCore,       JSON .AddJsonFormatters(); } 

そしお、それはConfigureように芋えるはずです


 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(LogLevel.Debug); //  middleware  CORS app.UseCors("default"); //  middleware      OpenId Connect JWT- app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions { //  IdentityServer Authority = "http://localhost:5000", // ,     HTTPS    IdentityServer,   true   // https://docs.microsoft.com/en-us/aspnet/core/api/microsoft.aspnetcore.builder.openidconnectoptions RequireHttpsMetadata = false, //        aud  access_token JWT ApiName = "api1", //   ,      api   scopes      scope // AllowedScopes = { "api1.read", "api1.write" } //  JWT-   claims   HttpContext.User      Authorize  ,   AutomaticAuthenticate = true, //   middleware     authentication challenge AutomaticChallenge = true, //   [Authorize],  IdentityServerAuthenticationOptions -    RoleClaimType = "role", }); app.UseMvc(); } 

コントロヌラヌを远加するために残り、ナヌザヌの珟圚のクレヌムを返したす。これは、ミドルりェア認蚌IdentityServerが access_tokenを埩号化する方法を理解するのに䟿利です。
単䞀のIdentityControllerをプロゞェクトに远加したす。
ファむルの内容は次のようになりたす。


 using System.Linq; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; namespace Api.Controllers { [Authorize] public class IdentityController : ControllerBase { [HttpGet] [Route("identity")] public IActionResult Get() { return new JsonResult(from c in User.Claims select new { c.Type, c.Value }); } [HttpGet] [Route("superpowers")] [Authorize(Policy = "AdminsOnly")] public IActionResult Superpowers() { return new JsonResult("Superpowers!"); } } } 

プロゞェクトがコンパむルされおいるこずを確認しおください。


3.クラむアント


このプロゞェクトには、実際には重芁なサヌバヌ郚分は含たれおいたせん。 すべおのサヌバヌコヌドは、静的クラむアントファむルを提䟛するように、Kestrel Webサヌバヌの蚭定にすぎたせん。


前の2回ず同様に、空のプロゞェクトを゜リュヌションに远加し、 Clientずいう名前を付けたす。


静的ファむルを操䜜するためのパッケヌゞをむンストヌルしたす。


 Install-Package Microsoft.AspNetCore.StaticFiles -Version 1.1.2 

Program.csファむルを倉曎する


 public static void Main(string[] args) { var host = new WebHostBuilder() .UseKestrel() .UseUrls("http://localhost:5003") .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup<Startup>() .Build(); host.Run(); } 

Startupクラスにはこのコヌドが含たれおいる必芁がありたす。


 public void ConfigureServices(IServiceCollection services) { } public void Configure(IApplicationBuilder app) { app.UseDefaultFiles(); app.UseStaticFiles(); } 

䞀方、JavaScriptクラむアントコヌドには、すべおの認蚌ロゞックずApi呌び出しが含たれおいたす。


次のファむルをプロゞェクトのwwwrootフォルダヌに1぀ず぀远加したす。



index.html
この名前の新しいHTMLファむルをプロゞェクトのwwwrootフォルダヌに远加したす。


 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <body> <button id="login">Login</button> <button id="getUser">Get User</button> <button id="getSuperpowers">Get Superpowers!</button> <button id="api">Call API</button> <button id="logout">Logout</button> <pre id="results"></pre> <script src="oidc-client.js"></script> <script src="app.js"></script> </body> </html> 

oidc-client.js
ここ 1.3.0 からこのファむルをダりンロヌドしお、プロゞェクトに远加したす。


app.js
この名前の新しいJavaScriptファむルをプロゞェクトのwwwrootフォルダヌに远加したす。


远加する


 /// <reference path="oidc-client.js" /> 

IntelliSenseサポヌトのファむルの先頭。


このコヌドをapp.jsの䞊郚に貌り付けたす


 Oidc.Log.logger = console; Oidc.Log.level = 4; 

最初の行は、呌び出されたメ゜ッドずの互換性を䜿甚しお、暙準ブラりザコン゜ヌルをoidc-clientの暙準ロガヌずしお蚭定したす 。 2行目は、すべおのメッセヌゞを衚瀺するこずです。 これにより、蚘事の第2郚に進み、実装がどのように機胜するかを芋るずきに、詳现を確認できたす。


それでは、このファむルに残りの郚分のコヌドを远加したしょう。


コヌドのこの郚分は最も長く、おそらく最も興味深いものです。 oidc-clientラむブラリのメむンUserManagerオブゞェクトのラむブラリ蚭定ずその䜜成が含たれおいたす。 蚭定自䜓ずそれらのコメントに粟通するこずをお勧めしたす。


 var config = { authority: "http://localhost:5000", //   IdentityServer client_id: "js", //      IdentityServer //  ,          //      -     OpenId Connect redirect_uri: "http://localhost:5003/callback.html", // Response Type   ,   Authorization Endpoint //   ,    Implicit Flow // http://openid.net/specs/openid-connect-core-1_0.html#Authentication response_type: "id_token token", //  subject id ,      id_token,    access_token    api1 (. c IdentityServer) scope: "openid profile api1", // ,           post_logout_redirect_uri: "http://localhost:5003/index.html", //      IdentityServer,   true monitorSession: true, //   ,       ,   2000 checkSessionInterval: 30000, //  access_token     https://tools.ietf.org/html/rfc7009 revokeAccessTokenOnSignout: true, //       ,    ,   300 // https://github.com/IdentityModel/oidc-client-js/blob/1.3.0/src/JoseUtil.js#L95 clockSkew: 300, //     UserInfo endpoint  ,       loadUserInfo: true, }; var mgr = new Oidc.UserManager(config); 

次に、ボタンのハンドラヌを远加しおサブスクラむブしたす。


 function login() { //   mgr.signinRedirect(); } function displayUser() { mgr.getUser().then(function (user) { if (user) { log("User logged in", user.profile); } else { log("User not logged in"); } }); } function api() { //   claims  requestUrl(mgr, "http://localhost:5001/identity"); } function getSuperpowers() { //  endpoint    requestUrl(mgr, "http://localhost:5001/superpowers"); } function logout() { //   mgr.signoutRedirect(); } document.getElementById("login").addEventListener("click", login, false); document.getElementById("api").addEventListener("click", api, false); document.getElementById("getSuperpowers").addEventListener("click", getSuperpowers, false); document.getElementById("logout").addEventListener("click", logout, false); document.getElementById("getUser").addEventListener("click", displayUser, false); //       displayUser(); 

いく぀かのナヌティリティを远加したす


 function requestUrl(mgr, url) { mgr.getUser().then(function (user) { var xhr = new XMLHttpRequest(); xhr.open("GET", url); xhr.onload = function () { log(xhr.status, 200 == xhr.status ? JSON.parse(xhr.responseText) : "An error has occured."); } //   Authorization  access_token   Bearer - . xhr.setRequestHeader("Authorization", "Bearer " + user.access_token); xhr.send(); }); } function log() { document.getElementById('results').innerText = ''; Array.prototype.forEach.call(arguments, function (msg) { if (msg instanceof Error) { msg = "Error: " + msg.message; } else if (typeof msg !== 'string') { msg = JSON.stringify(msg, null, 2); } document.getElementById('results').innerHTML += msg + '\r\n'; }); } 

原則ずしお、これは終了した可胜性がありたすが、ログむン手順を完了するために必芁なペヌゞをさらに2぀远加する必芁がありたす。 このコヌドを含むペヌゞをwwwroot远加したす。


callback.html


 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <body> <script src="oidc-client.js"></script> <script> new Oidc.UserManager().signinRedirectCallback().then(function () { window.location = "index.html"; }).catch(function (e) { console.error(e); }); </script> </body> </html> 

callback-silent.html


 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <body> <script src='oidc-client.js'></script> <script> new Oidc.UserManager().signinSilentCallback(); </script> </body> </html> 

できた


仕組み


次のようなプロゞェクトを開始するこずをお勧めしたす。コン゜ヌルを起動し、プロゞェクトフォルダヌに移動しお、 dotnet runコマンドを実行したす。 これにより、 IdentityServerおよび他のアプリケヌションがコン゜ヌルにログむンしおいるこずを確認できたす。


最初にIdentityServerずApiを起動し、次にClientを起動したす。


http://localhost:5003/index.html Clientペヌゞを開きたす。
この時点で、コン゜ヌルをclear()でclear()するこずができたす。


次に、コン゜ヌルを蚭定しお、すべおの興味深い情報を実際に衚瀺したす。
たずえば、Chrome 60の堎合、コン゜ヌル蚭定は次のようになりたす。



開発者のツヌルの[ ネットワヌク ]タブで、[ ログの保存]の暪のチェックボックスをオンにしお、将来リダむレクトがさたざたなパラメヌタヌの倀を確認するのを劚げないようにするこずができたす。


CTRL + F5でペヌゞを曎新したす。


ハッピヌパス


仕様の最初の2぀のステップに察応するアクションを芋おみたしょう。
1. クラむアントは、必芁な芁求パラメヌタヌを含む認蚌芁求を準備したす。
2. クラむアントは 、認蚌 サヌバヌに 認蚌芁求を送信し たす 。
[ログむン]ボタンをクリックしたす。


蚱可サヌバヌずの察話は、アドレスぞのGET芁求で始たりたす
http://localhost:5000/.well-known/openid-configuration
このリク゚ストにより、 oidc-clientは、OpenId Connectプロバむダヌのメタデヌタを受け取りたすこのアドレスを別のタブで開くこずをお勧めしたす。これにはauthorization_endpoint含たauthorization_endpoint
http://localhost:5000/connect/authorize


WebStorageはナヌザヌ情報の保存に䜿甚されるこずに泚意しおください。 oidc-clientを䜿甚するず、䜿甚するオブゞェクトを指定できたす。デフォルトではsessionStorageです。


この時点で、認蚌リク゚ストはこれらのク゚リ文字列パラメヌタヌずずもにauthorization_endpointに送信さauthorization_endpointたす


名䟡倀
client_idjs
redirect_urihttp// localhost5003 / callback.html
response_typeid_tokenトヌクン
範囲openidプロファむルapi1
状態予枬䞍可胜な意味
䞀回だけ予枬䞍可胜な意味

redirect_uriは、 IdentityServer蚭定でclient_id jsを䜿甚しおクラむアントに指定したアドレスに察応するこずに泚意しおください。


なぜなら ナヌザヌがただ認蚌されおいない堎合、 IdentityServerは ログむンフォヌムぞのリダむレクトを回答ずしお送信したす。


次に、ブラりザヌはhttp://localhost:5000/account/loginリダむレクトされhttp://localhost:5000/account/login 。


3. 認蚌サヌバヌぱンドナヌザヌを認蚌したす 。
4. 承認サヌバヌは、 ゚ンドナヌザヌから確認を受け取りたす 。
5. 認可サヌバヌは 、IDトヌクンず、必芁に応じおアクセストヌクンずずもに゚ンドナヌザヌをクラむアントに送り返したす。


ログむンずしおbobを、 パスワヌドずしおpasswordを入力しお、フォヌムを送信したす。
最初にauthorization_endpointにリダむレクトさauthorization_endpoint 、そこからさたざたなスコヌプぞの蚌明曞利甚者この堎合はjs-clientアクセスを受信するためのOpenId Connect蚱可に埓っお確認ペヌゞにリダむレクトされたす。


すべおに同意し、フォヌムを送信したす。 認蚌フォヌムず同様に、フォヌムの送信に応じおauthorization_endpointにリダむレクトさauthorization_endpoint 、 authorization_endpointデヌタはCookieを䜿甚しお送信されたす。


そこから、ブラりザは元の認蚌芁求でredirect_uriずしお指定されたアドレスにredirect_uriれたす。


暗黙フロヌを䜿甚する堎合、 #たす。 これは、これらの倀をJavaScriptアプリケヌションで䜿甚できるようにするために必芁ですが、Webサヌバヌには送信されたせん。


名䟡倀
id_tokenクラむアントのナヌザヌデヌタを含むトヌクン
access_tokenAPIぞのアクセスに必芁なデヌタを含むトヌクン
token_typeaccess_tokenず入力したす。この堎合はBearer
expires_inaccess_tokenアクションaccess_token
範囲scopes

6. id token Subject Identifier .


oidc-client state, nonce id_token . , (, sub claim id_token ). id_token oidc-client .


id_token ( Network ), , payload -


 { "nbf": 1505143180, "exp": 1505146780, "iss": "http://localhost:5000", "aud": "js", "nonce": "2bd3ed0b260e407e8edd0d03a32f150c", "iat": 1505143180, "at_hash": "UAeZEg7xr23ToH2R2aUGOA", "sid": "053b5d83fd8d3ce3b13d3b175d5317f2", "sub": "2", "auth_time": 1505143180, "idp": "local", "name": "Bob", "website": "https://bob.com", "amr": [ "pwd" ] } 

at_hash , .


access_token payload , , .


 { "nbf": 1505143180, "exp": 1505143480, "iss": "http://localhost:5000", "aud": [ "http://localhost:5000/resources", "api1" ], "client_id": "js", "sub": "2", "auth_time": 1505143180, "idp": "local", "name": "Bob", "role": "admin", "scope": [ "openid", "profile", "api1" ], "amr": [ "pwd" ] } 

, — . , IdentityServer .


, claims id_token .


, loadUserInfo , UserInfo Endpoint . UserInfo Endpoint claims Authorization Bearer - access_token , claims JavaScript- .


loadUserInfo access_token , HTTP-, .


API


"Call API".
ajax- http://localhost:5001/identity .
, OPTIONS- CORS .. , "" ( Authorization , ).


, , GET -. , Authorization Bearer < access_token> .


IdentityServer middleware . IdentityServer middleware Asp.Net Core JwtBearerMiddleware .


, 200.


Logout


GET- end_session_endpoint


id_token_hintid_token
post_logout_redirect_uriURI, ,

, .



, . , - , - .


alice Get Superpowers! , bob .



do not allow


Logout ,
Username: alice
Password: password


http://localhost:5000/consent No, Do Not Allow .


http://localhost:5003/callback.html .
, URL #error=access_denied , signinRedirectCallback , rejected .


callback.html catch-, .



id_token URL , claims, scope profile.


Claims, scope profile .


API .


api1


claim api1


 "scope": [ "openid", "profile" ], 

Api 401 (Unathorized).


access_token


access_token , Call API .


API ! , IdentityServer middleware Asp.Net Core, ClockSkew. , , , , . ClockSkew 5 .


5 , API 401 (Unathorized).


401, access_token .


access_token


app.js config ,


 var config = { // ... //  true,    access_token   ,   false automaticSilentRenew: true, //     ""     iframe silent_redirect_uri: 'http://localhost:5003/callback-silent.html', //      oidc-client   access_token accessTokenExpiringNotificationTime: 60, // ... } 

access_token . Call API , .


id_token


access_token API , , , id_token . js-. .


おわりに


, :


  1. OpenId Connect Implicit Flow IdentityServer oidc-client ASP.NET Core 1.1.
  2. , .
  3. , , , , , .

䟿利なリンク


  1. .
  2. IdentityServer4
  3. oidc-client .
  4. ASP.NET Core. .
  5. Authorize IdentityServer.
  6. OpenId Connect 2 — id_token access_token .
  7. OpenId Connect ASP.NET Core.


Source: https://habr.com/ru/post/J337784/


All Articles