本文為 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