本文為 OpenID Connect 簡化模式(implicit)
已更新至.NET Core 2.2
在本快速入門中,我們希望通過 OpenID Connect 協議向我們的 IdentityServer 添加對用戶認證交互的支持。
我們將創建一個將使用 IdentityServer 進行身份認證的MVC應用程序。
添加UI
OpenID Connect 所需的所有協議支持都已內置到 IdentityServer 中。您需要為提供必要的UI部件:登錄,注銷,同意授權和錯誤頁面。
根據業務場景的不同對 IdentityServer 的實現也有所不同,但我們提供了一個基於 MVC 的示例UI,您可以將其用作起步。
可以在快速入門UI倉庫中找到此UI。 您可以克隆或下載此repo,並將Controller,View,Model和CSS放入IdentityServer Web 應用程序中。
或者,您可以使用.NET CLI(從 src/IdentityServer 文件夾中運行命令):
dotnet new is4ui
添加 MVC UI 后,您還需要在 DI 系統和管道中啟用 MVC。 當您查看Startup.cs時,您將在 ConfigureServices 和 Configure 方法中找到有關如何啟用MVC的注釋。
運行IdentityServer應用程序,您現在應該看到一個主頁。
花一些時間檢查控制器和模型,您越了解它們,就越容易掌握以便修改。 大多數代碼使用“feature folder”樣式存在於“Quickstart”文件夾中。 如果此樣式不適合您,請隨意以您想要的任何方式組織代碼。
創建 MVC 客戶端
接下來,您將向您的解決方案添加MVC應用程序。 使用 ASP.NET Core “Web Application” (即 MVC) 模板。 不要在向導中配置“Authentication"設置 - 您將在此快速入門中手動執行此操作。 創建項目后,將應用程序配置為在端口5002上運行。
要將對 OpenID Connect 身份認證的支持添加到MVC應用程序,請在Startup中將以下內容添加到ConfigureServices :
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ClientId = "mvc";
options.SaveTokens = true;
});
}
AddAuthentication將身份認證服務添加到 DI。 我們使用 cookie 來本地登錄用戶(通過“Cookies”作為DefaultScheme),我們將 DefaultChallengeScheme 設置為“oidc”,因為當我們需要用戶登錄時,我們將使用OpenID Connect 協議。
然后,我們使用 AddCookie 添加可以處理 cookie 的處理程序。
最后,AddOpenIdConnect用於配置執行 OpenID Connect 協議的處理程序。Authority表明我們信任的 IdentityServer 地址。然后我們通過ClientId。識別這個客戶端。 SaveTokens用於在 cookie 中保留來自IdentityServer 的令牌(稍后將需要它們)。
同樣,我們已經關閉了 JWT Claim類型映射,以允許常用的Claim(例如'sub'和'idp')。
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
然后要確保認證服務執行對每個請求的驗證,加入UseAuthentication到Configure中:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseAuthentication();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}
應在管道中的MVC之前添加認證中間件。
最后一步是觸發身份認證。為此,請轉到 Controller 並添加[Authorize]特性到其中一個Action。還要修改主視圖以顯示用戶的Claim以及cookie屬性:
@using Microsoft.AspNetCore.Authentication
<h2>Claims</h2>
<dl>
@foreach (var claim in User.Claims)
{
<dt>@claim.Type</dt>
<dd>@claim.Value</dd>
}
</dl>
<h2>Properties</h2>
<dl>
@foreach (var prop in (await Context.AuthenticateAsync()).Properties.Items)
{
<dt>@prop.Key</dt>
<dd>@prop.Value</dd>
}
</dl>
如果您現在使用瀏覽器訪問該控制器,將會被重定向到IdentityServer - 這將導致錯誤,因為MVC客戶端尚未注冊。
添加 OpenID Connect Identity Scope
與OAuth 2.0類似,OpenID Connect也使用Scope概念。同樣,Scope代表您想要保護的內容以及客戶端想要訪問的內容。與OAuth相比,OIDC中的Scope不僅代表API資源,還代表用戶ID,姓名或電子郵件地址等身份資源。
通過修改 Config.cs 中的 GetIdentityResources 方法,添加對標准 openid(subject id)和profile (名字,姓氏等)Scope的支持:
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
};
}
所有標准Scope及其相應的Claim都可以在OpenID Connect規范中找到。
添加OpenID Connect簡化流程客戶端
最后一步是將MVC客戶端的配置信息添加到 IdentityServer。
基於OpenID Connect的客戶端與我們目前添加的OAuth 2.0客戶端非常相似。但由於OIDC中的流程始終是交互式的,因此我們需要在配置中添加一些重定向URL。
將以下內容添加到客戶端配置中:
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
// other clients omitted...
// OpenID Connect implicit flow client (MVC)
new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.Implicit,
// 登錄成功回調處理地址,處理回調返回的數據
RedirectUris = { "http://localhost:5002/signin-oidc" },
// where to redirect to after logout
PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
}
}
};
}
測試客戶端
通過訪問到受保護的Controller操作來觸發身份認證。您應該會看到重定向到IdentityServer的登錄頁面。

成功登錄后,將向用戶顯示同意授權頁面。在這里,用戶可以決定是否要將他的身份信息發布到客戶端應用程序。
可以使用客戶端配置上
RequireConsent的屬性關閉同意授權頁面。

之后,IdentityServer將重定向回MVC客戶端,其中OpenID Connect身份認證處理程序處理響應並通過設置 cookie 在本地登錄用戶。最后,MVC視圖將顯示cookie的內容。

如您所見,cookie 包含兩部分,即用戶的Claim和一些元數據。此元數據還包含IdentityServer發出的原始令牌。可以將此令牌復制到jwt.io以檢查其內容。
添加注銷
后一步是向MVC客戶端添加注銷。
使用IdentityServer等身份認證服務,僅清除本地應用程序cookie是不夠的。此外,您還需要向IdentityServer進行往返交互以清除中央單點登錄會話。
確切的協議步驟在OpenID Connect處理程序中實現,只需將以下代碼添加到某個控制器即可觸發注銷:
public IActionResult Logout()
{
return SignOut("Cookies", "oidc");
}
這將清除本地cookie,然后重定向到IdentityServer。IdentityServer將清除其cookie,然后為用戶提供返回MVC應用程序的鏈接。
進一步的實驗
如上所述,OpenID Connect處理程序默認要求 profile scope。此Scope還包括 name 或者 website。
讓我們將這些Claim添加到用戶信息中,以便IdentityServer可以將它們放入 identity token:
public static List<TestUser> GetUsers()
{
return new List<TestUser>
{
new TestUser
{
SubjectId = "1",
Username = "alice",
Password = "password",
Claims = new []
{
new Claim("name", "Alice"),
new Claim("website", "https://alice.com")
}
},
new TestUser
{
SubjectId = "2",
Username = "bob",
Password = "password",
Claims = new []
{
new Claim("name", "Bob"),
new Claim("website", "https://bob.com")
}
}
};
}
下次進行身份認證時,您的Claim頁面現在會顯示這些Claim。
添加更多Claim - 以及更多Scope。OpenID Connect中間件上的Scope屬性是您配置在身份認證期間將哪些Scope發送到IdentityServer。
值得注意的是,對令牌Claim的檢索是一個可擴展點--IProfileService。 由於我們使用的是AddTestUsers,因此默認使用TestUserProfileService。 您可以在此處檢查源代碼以查看其工作原理,以便實現自定義Claim檢索。
資料
本文 Demo:3_ImplicitFlowAuthentication
