IdentityServer4之Implicit(隱式許可)
IdentityServer4之Implicit(隱式許可)
參考
官方文檔:3_interactive_login 、7_javascript_client
概念:隱式許可
認證服務端配置
認證服務ApiResource配置
new ApiResource("api1", "api項目 一") { ApiSecrets = { new Secret("api1pwd".Sha256()) } },
認證服務Client配置
// OpenID Connect implicit flow client (MVC) new Client { ClientId = "mvc", ClientName = "MVC Client", AllowedGrantTypes = GrantTypes.Implicit, AllowAccessTokensViaBrowser = true, AccessTokenType = AccessTokenType.Reference, RedirectUris ={ "http://localhost:5002/signin-oidc", "http://www.implicit.com/signin-oidc" }, PostLogoutRedirectUris={ "http://localhost:5002/signout-callback-oidc", "http://www.implicit.com/signout-callback-oidc" }, AllowedScopes = { IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Profile, "api1","api2" } },
認證服務Startup配置
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); // configure identity server with in-memory stores, keys, clients and scopes services.AddIdentityServer() .AddDeveloperSigningCredential() .AddInMemoryIdentityResources(Config.GetIdentityResources()) .AddInMemoryApiResources(Config.GetApiResources()) .AddInMemoryClients(Config.GetClients()) .AddTestUsers(Config.GetUsers()); }
資源服務Api配置
資源服務器Startup配置
services.AddMvcCore() .AddAuthorization() .AddJsonFormatters(); services.AddAuthentication("Bearer") .AddIdentityServerAuthentication(options => { options.Authority = "http://localhost:5000"; options.RequireHttpsMetadata = false; options.ApiName = "api1"; options.ApiSecret = "api1pwd"; //對應ApiResources中的密鑰 });
添加接口
[Route("[controller]")] [Authorize] public class IdentityController : ControllerBase { [HttpGet] public IActionResult Get() { var info = from c in User.Claims select new { c.Type, c.Value }; var list = info.ToList(); list.Add(new { Type = "api1返回", Value = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }); return new JsonResult(list); } }
Client客戶端
(A)客戶端通過向授權端點引導資源擁有者的用戶代理開始流程。客戶端包括它的客戶端標識、請求範圍、本地狀態和重定向URI,一旦訪問被許可(或拒絕)授權服務器將傳送用戶代理回到該URI。
(B)授權服務器驗證資源擁有者的身份(通過用戶代理),並確定資源擁有者是否授予或拒絕客戶端的訪問請求。
(C)假設資源擁有者許可訪問,授權服務器使用之前(在請求時或客戶端註冊時)提供的重定向URI重定向用戶代理回到客戶端。重定向URI在URI片段中包含訪問令牌。
(D)用戶代理順著重定向指示向Web托管的客戶端資源發起請求。用戶代理在本地保留片段信息。
(E)Web托管的客戶端資源返回一個網頁(通常是帶有嵌入式腳本的HTML文檔),該網頁能夠訪問包含用戶代理保留的片段的完整重定向URI並提取包含在片段中的訪問令牌(和其他參數)。
(F)用戶代理在本地執行Web托管的客戶端資源提供的提取訪問令牌的腳本。
(G)用戶代理傳送訪問令牌給客戶端。
1、JS Client
// JavaScript Client new Client { ClientId = "js", ClientName = "JavaScript Client", AllowedGrantTypes = GrantTypes.Implicit, AllowAccessTokensViaBrowser = true, //允許通過瀏覽器傳輸token RedirectUris = { "http://localhost:5009/callback.html" }, PostLogoutRedirectUris = { "http://localhost:5009/index.html" }, AllowedCorsOrigins = { "http://localhost:5009" }, AllowedScopes = { IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Profile, "api1" } },
js client的靜態資源。
2、MVC Client
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); services.AddAuthentication(options => { options.DefaultScheme = "Cookies"; options.DefaultChallengeScheme = "oidc"; }) .AddCookie("Cookies") .AddOpenIdConnect("oidc", options => { options.SignInScheme = "Cookies"; options.Authority = "http://localhost:5000"; options.RequireHttpsMetadata = false; options.ClientId = "mvc"; options.ResponseType = "id_token token"; options.SaveTokens = true; options.GetClaimsFromUserInfoEndpoint = true; options.Scope.Add("api1"); });
需要身份授權的頁面
[Authorize] public IActionResult Secure() { ViewData["Message"] = "Secure page."; return View(); }
調用Api
public async Task<IActionResult> CallApiUsingUserAccessToken() { var accessToken = await HttpContext.GetTokenAsync("access_token"); var client = new HttpClient(); client.SetBearerToken(accessToken); var content = await client.GetStringAsync("http://localhost:5001/identity"); ViewBag.Json = JArray.Parse(content).ToString(); return View("json"); }
獲取token過程解析
Reference形式獲取access_token
1、前後端分離形式認證
隱式許可沒有獲取Authorization Code的過程。
4和5是是用戶登錄(資源擁有者授權)。
2和3為Get請求參數如下。
使用工具請求實際得到的是一個js Web-Hosted Client Resource返回的靜態腳本資源 。
304的回調 # 後的信息不會經過js client 的服務器,直接在瀏覽器解析。
http://localhost:5009/callback.html# id_token=eyJhbGciOiJSUzI1NiIsImtpZCI6IjAzMTZkNWQwYTViNTgyYzc0NmJlMmVhZWU1MTg1NzhiIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MTE5NTY1NTMsImV4cCI6MTUxMTk1Njg1MywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjoianMiLCJub25jZSI6ImEyOGY5MmRiMjVmNzRkYjQ5YTRhMzU3YTY0YzA2OTU2IiwiaWF0IjoxNTExOTU2NTUzLCJhdF9oYXNoIjoiUldXMU9pTHNzYmVHek1UaHBkbE1xdyIsInNpZCI6ImZiODI5MzQzYWRjN2U4MjUxMjk1OTE1NDBmZDc3ZjBhIiwic3ViIjoiMSIsImF1dGhfdGltZSI6MTUxMTk1NjU1MywiaWRwIjoibG9jYWwiLCJhbXIiOlsicHdkIl19.av1-FqeVdobrPl1QxrIndjpzwTHgoJTclx2xwaOexDapbi-yYe8uOIBQG3hR4B4juM3nBm5GFp0873Yn_ReUD4YAxKlBJuoVxzMVIxSVB2H7RZH5wiMCktY8rgWAV4_lSfDZG1B3n4Ged8gj80b5vlt6rKs48woJiaeDemtLs0EY6lqomENy0MY1lu2TkVco_AyB_ha6jJsLXgCK8U9ttN6862h0HlvDy7KqRpTqfstkcT1JIUkooX3JfUNwru4y38HIxs55_dA9Pq8hfBK--Y7_fRW2_vnDz99Bn0kRcQcfgHXHxcovtNU1MRdFataRtjP6QyC26DyXLcr5d8_QCw& access_token=eyJhbGciOiJSUzI1NiIsImtpZCI6IjAzMTZkNWQwYTViNTgyYzc0NmJlMmVhZWU1MTg1NzhiIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MTE5NTY1NTMsImV4cCI6MTUxMTk2MDE1MywiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjpbImh0dHA6Ly9sb2NhbGhvc3Q6NTAwMC9yZXNvdXJjZXMiLCJhcGkxIl0sImNsaWVudF9pZCI6ImpzIiwic3ViIjoiMSIsImF1dGhfdGltZSI6MTUxMTk1NjU1MywiaWRwIjoibG9jYWwiLCJzY29wZSI6WyJvcGVuaWQiLCJwcm9maWxlIiwiYXBpMSJdLCJhbXIiOlsicHdkIl19.s1lYjwnuj6PKYwUpKj7CNFhKPEBFqbI51UT8okg1G8d73AU1Tx1KuZpkulxeAbhIqD807TiY_A9-h1shSNTAXOhlcSGR6hZiMHcAU50nFvkNTq16j0wjeGtF5i5xlNJDwvq77cDs0rWnge9dmPtQZNPQXWfNW49_A7BRQUDiAad5S3I0juYsvYS7HThf0dGXRiJwI8ZYNMDRT2jxthZRaImuQFNK3VAFNptb8rJ2R5D3oBbHWDriJ4N-6UUE36ICPenmhy-aykGm_bNjD_unm6sEKy7hGTboGetpgt4F_4fAKJQCCrEzfUohXvQwUSEjQoE1RlZssIFCQTdYnG86sw& token_type=Bearer& expires_in=3600& scope=openid%20profile%20api1& state=49773b518261412199fb3ece49a043e1& session_state=yMpEMT7X9xYpM8aBRpJ8IWK60zUi71jXzIgRSaCHO14.6d673e3200de918c6c35a5d61b4ddd2e
2、OpenID Connect協議認證
7和22是用戶登錄(資源擁有者授權)。
5和23為Get請求參數如下。
使用工具請求實際得到的是一個自動提交的表單。
登錄完成後的效果。
IdentityServer4之Implicit(隱式許可)