IdentityServer4 是一個提供 認證服務,單點登錄/登出(SSO),API訪問控制,聯合認證通道的可定製、免費商業支持的框架。 ...
IdentityServer4 中文文檔 -11- (快速入門)添加基於 OpenID Connect 的用戶認證
原文:http://docs.identityserver.io/en/release/quickstarts/3_interactive_login.html
上一篇:IdentityServer4 中文文檔 -10- (快速入門)使用密碼保護API
下一篇:IdentityServer4 中文文檔 -12- (快速入門)添加外部認證支持
在這個快速啟動中,我們希望通過OpenID Connect協議向我們的 IdentityServer 添加對互動式用戶身份驗證的支持。
完成之後,我們將創建一個使用 IdentityServer 進行身份認證的 MVC 應用程式。
添加 UI(用戶界面)
IdentityServer 內置了 OpenID Connect 需要的所有協議支持。你需要提供必需的 UI 部分,包括 登錄、註銷、授權確認以及錯誤頁。
因為在每個 IdentityServer 的實現中,視覺、感覺以及實際工作流可能總是有所不同的,所以我們提供了一套基於 MVC 的樣例 UI,你可以將其作為啟動點來使用。
這套 UI 可以在 快速入門倉庫 找到。你還可以克隆或下載這個倉庫,將其中的控制器、視圖、模型以及 CSS 放到你的 Web 應用程式中。
你還可以在你的 Web 應用程式中以命令行的方式運行以下命令來自動下載:
iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/release/get.ps1'))
查看 自述文件 以瞭解更多 快速入門UI 相關的信息。
註意: UI 倉庫的
release
分支擁有與最新發佈的穩定版相匹配的 UI。dev
分支則與 IdentityServer4 的當前開發構建相符。如果你想要尋找指定版本的 UI,請查看相應的標簽。
花一些時間去查閱控制器和模型,你越是瞭解他們,將來要修改他們就越簡單。大部分代碼都以“功能目錄”的樣式放在 “Quickstart” 文件夾下,如果這種樣式不適合你,那就按照你想要的方式隨意組織代碼。
創建一個 MVC 客戶端
接下來你將向解決方案添加一個 MVC 應用程式,可以使用 ASP.NET Core "Web 應用程式" 模板來實現。 將應用程式配置為使用 5002 埠(可以查看概覽部分以瞭解如何配置)。
為了能向 MVC 應用程式添加 OpenID Connect 認證支持,請添加如下 NuGet 程式包:
- Microsoft.AspNetCore.Authentication.Cookies
- Microsoft.AspNetCore.Authentication.OpenIdConnect
然後添加這兩個中間件到你的管道中 —— Cookies 對應的中間件很簡單:
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationScheme="Cookies"
});
OpenID Connect 中間件需要稍微多一些配置。將它指向 Identity Server,指定一個客戶端 ID 並且告訴它哪個中間件將會負責本地登陸(也就是 cookies 中間件)。此外,我們關閉了 JWT 身份信息類型映射,這樣就允許 well-known 身份信息(比如,“sub” 和 “idp”) 無干擾地流過。這個身份信息類型映射的 “清理” 必須在調用 UseOpenIdConnectAuthentication()
之前完成:
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
AuthenticationScheme = "oidc",
SignInScheme = "Cookies",
Authority = "http://localhost:5000",
RequireHttpsMetadata = false,
ClientId = "mvc",
SaveTokens = true
});
兩個中間件都應該在 MVC 之前添加到管道。
下一個步驟是觸發認證握手,為此打開 home
控制器並添加 [Authorize]
到其中一個 action
上。另外,修改 action 對應的視圖以顯示用戶的身份信息,比如:
<dl>
@foreach (var claim in User.Claims)
{
<dt>@claim.Type</dt>
<dd>@claim.Value</dd>
}
</dl>
現在,如果你使用瀏覽器導航到上述控制器,一個Mvc客戶端將視圖重定向到 IdentityServer - 這會導致錯誤,因為 MVC 客戶端還沒有註冊(在 IdentityServer 上定義)呢。
添加 OpenID Connect 身份 Scopes 支持
與 OAuth 2.0 相似,OpenID Connect 也使用 scopes 這個概念。再一次說明,Scopes 表示你想要保護的和客戶端想要訪問的事物。在與 OAuth 相比,OIDC(OpenID Connect) 中的 scopes 不僅代表 API,還代表了諸如 用戶id、用戶名 或 郵箱地址等身份數據。
通過(在 Config.cs 中)添加新的幫助器來創建 IdentityResource
對象的集合,可以添加對標準 openid
(subject id,這裡指的是用戶id)和 profile
(姓氏,名稱 等等)等 scopes 的支持:
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
};
}
註意:所有標準的 Scopes 和他們對應的 身份信息 都可以在 OpenID Connect 規範 中找到。
接下來在 Startup.cs
中你要將這些身份資源添加到你的 IdentityServer 配置。在你調用 AddIdentityServer()
的地方使用 AddInMemoryIdentityResources
擴展方法即可:
public void ConfigureServices(IServiceCollection services)
{
// 使用記憶體存儲,密鑰,客戶端和資源來配置身份伺服器。
services.AddIdentityServer()
.AddTemporarySigningCredential()
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetUsers())
.AddInMemoryIdentityResources(Config.GetIdentityResources());
}
為 OIDC 隱式流添加客戶端定義
最後一個步驟是為 IdentityServer 添加一個新的客戶端。
目前,我們添加的基於 OIDC 的客戶端與 OAuth 2.0 客戶端非常相似。但是由於 OIDC 中的流總是互動式的,所以我們需要添加一些重定向 URL 到我們的配置中。
添加以下代碼到你的客戶端配置中:
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
// 省略的客戶端...
// OIDC 隱式流客戶端(MVC)
new Client
{
ClientId = "mvc",
ClientName = "Mvc 客戶端",
AllowedGrantTypes = GrantTypes.Implicit,
// 登錄後重定向到的地址
RedirectUris = { "http://localhost:5002/signin-oidc" },
// 註銷後重定向到的地址
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
}
}
};
}
測試 MVC 客戶端
現在,對於新的 MVC 客戶端,一切都準備好了。
將瀏覽器導航到受保護的 控制器 action 以觸發認證握手。你應該能看到客戶端將你重定向到了 IdentityServer 的登錄頁。
登錄成功後,用戶將在授權確認頁中被呈現出來。在這裡用戶可以決定他是否想要發佈他的身份信息給客戶端應用程式。
註意: 授權確認頁可以通過客戶端定義對象的
RequireConsent
屬性被關閉(以每個客戶端為單位)。
最終瀏覽器將被重定向回客戶端應用程式,即展示用戶的身份信息。
註意:在開發期間你有時候可能會看到 無法驗證令牌 的異常信息。這是因為實際上簽名密鑰材料是憑空產生的,並且在只記憶體中駐留。這個異常在 客戶端 與 IdentityServer 不同步時就會發生。簡單地重覆客戶端上的操作,等到下一次元數據被捕獲時,一切都會再次正常工作的。
添加註銷
最後的最後,是給 MVC 客戶端添加 註銷功能。
通過 IdentityServer 這樣的服務進行身份認證,單單清除本地應用程式的 Cookies 是不夠的。你還需要往返一次 IdentityServer 來清理集中式單點登錄會話。
具體的協議步驟都在 OpenID Connect 中間件中實現了,簡單地添加以下代碼到某個控制器中就可以用來觸發註銷:
public async Task Logout()
{
await HttpContext.Authentication.SignOutAsync("Cookies");
await HttpContext.Authentication.SignOutAsync("oidc");
}
進一步實驗
如前面所說,OpenID Connect 中間件預設會請求 profile scope。這個 scope 還包含了用戶名或個人主頁等身份信息。
讓我們將這些身份信息添加到用戶定義裡面,這樣的話 IdentityServer 就可以把它們放到身份令牌中了:
public static List<TestUser> GetUsers()
{
return new List<TestUser>()
{
new TestUser
{
SubjectId="1",
Username="愛麗絲",
Password="password",
Claims = new []
{
new Claim("name", "愛麗絲"),
new Claim("website", "https://alice.com")
}
},
new TestUser
{
SubjectId="2",
Username="博德",
Password="password",
Claims = new []
{
new Claim("name", "博德"),
new Claim("website", "https://bob.com")
}
}
};
}
下一次你認證的時候,你的身份信息頁將會顯示額外的身份信息。
請隨意添加更多的身份信息 - 還有更多的 scopes。OpenID Connect 中間件上的 Scope
屬性是你用來配置哪些 Scopes 將在認證期間被髮送到 IdentityServer 的地方。
值得註意的是,對令牌中身份信息的遍歷是一個擴展點 - IProfileService
。因為我們正在使用 AddTestUser
,所以預設使用的是 TestUserProfileService
。你可以檢出這裡的源代碼來查看它的工作原理。
上一篇:IdentityServer4 中文文檔 -10- (快速入門)使用密碼保護API
下一篇:IdentityServer4 中文文檔 -12- (快速入門)添加外部認證支持