IdentityServer4 快速入門#3: 使用OpenID Connect隱式流程進行用戶身份驗證

注意

對于任何先決條件(例如模板),請先查看概述。
在本快速入門中,我們希望通過OpenID Connect協議向我們的IdentityServer添加對交互式用戶身份驗證的支持。
安裝好之后,我們將創建一個將使用IdentityServer進行身份驗證的MVC應用程序。

添加UI

Identity Server已內置OpenID Connect所需的所有協議支持。 您需要提供登錄,注銷,同意和錯誤所需的UI部分。

雖然外觀和確切的工作流程在每個IdentityServer實施中可能總是會有所不同,但我們提供了一個基于MVC的示例UI,您可以將其用作起點。

您可以在快速入門用戶界面存儲庫中找到該用戶界面。 您可以克隆或下載此存儲庫,然后將控制器,視圖,模型和CSS放到IdentityServer Web應用程序中。

或者,您可以使用.NET CLI(從src/IdentityServer文件夾中運行):

dotnet new is4ui

添加MVC UI后,還需要在DI系統和管道中啟用MVC。 當您查看Startup.cs時,您會在ConfigureServicesConfigure方法中找到注釋,這些注釋告訴您如何啟用MVC。

運行IdentityServer應用程序,您現在應該看到一個主頁。

花一些時間檢查控制器和模型,您對它們的了解越深入,將來進行修改的難度就越大。 大多數代碼使用“功能文件夾”樣式保存在“快速入門”文件夾中。 如果這種風格不適合您,請隨時以所需的任何方式組織代碼。

創建一個MVC客戶端

接下來,您將在解決方案中添加一個MVC應用程序。 為此,請使用ASP.NET Core“ Web應用程序”(即MvcClient)模板。 不要在向導中配置“Authentication”設置-您將在此快速入門中手動進行設置。 創建項目后,將應用程序配置為在端口5002上運行。

要將對OpenID Connect身份驗證的支持添加到MVC應用程序,請在Startup.cs中的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用于將IdentityServer中的令牌保留在cookie中(稍后將需要它們)。

同樣,我們已關閉JWT聲明類型映射,以允許眾所周知的聲明(例如“ sub”和“ idp”)不受干擾地流過:

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

然后,要確保身份驗證服務對每個請求執行,在Startup.csd文件中的Configure方法添加 UseAuthentication:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseAuthentication();

    app.UseStaticFiles();
    app.UseMvcWithDefaultRoute();
}

認證中間件應在管道中的MVC之前添加。

最后一步是觸發身份驗證握手。 為此,轉到Home控制器,并在其中一項操作上添加[Authorize]。 還修改Home View文件以顯示用戶的聲明以及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也使用范圍概念。 同樣,范圍代表您要保護的內容以及客戶端要訪問的內容。 與OAuth相比,OIDC中的范圍不代表API,而是身份數據,例如用戶ID,名稱或電子郵件地址。

通過修改Config.cs中的GetIdentityResources方法,添加對標準openid(主題id)和profile(名字,姓氏等)范圍的支持:

public static IEnumerable<IdentityResource> GetIdentityResources()
{
    return new List<IdentityResource>
    {
        new IdentityResources.OpenId(),
        new IdentityResources.Profile(),
    };
}
注意

所有標準范圍及其相應的聲明均可在OpenID Connect規范中找到

為OpenID Connect隱式流添加客戶端

最后一步是將MVC客戶端的新配置條目添加到IdentityServer。

基于OpenID Connect的客戶端與到目前為止我們添加的OAuth 2.0客戶端非常相似。 但是由于OIDC中的流始終是交互的,因此我們需要向配置中添加一些重定向URL。

將以下內容添加到您的客戶端配置中:

public static IEnumerable<Client> GetClients()
{
    return new List<Client>
    {
        // 其他代碼省略...

        // OpenID Connect隱式流MVC客戶端
        new Client
        {
            ClientId = "mvc",
            ClientName = "MVC Client",
            AllowedGrantTypes = GrantTypes.Implicit,

            // 登錄后重定向到的位置
            RedirectUris = { "http://localhost:5002/signin-oidc" },

            // 注銷后重定向到的位置
            PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },

            AllowedScopes = new List<string>
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile
            }
        }
    };
}

測試客戶端

現在終于可以為新的MVC客戶端準備好一切了。

通過導航到受保護的控制器操作來觸發身份驗證握手。 您應該看到重定向到IdentityServer上的登錄頁面。

image.png

成功登錄后,將向用戶顯示同意屏幕。 用戶可以在此處決定是否要將其身份信息發布到客戶端應用程序。

注意

可以使用客戶端配置上的RequireConsent屬性在每個客戶端上關閉同意。

image.png

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

如您所見,cookie包含兩部分,用戶聲明和一些元數據。 此元數據還包含由IdentityServer發行的原始令牌。 可以將此令牌復制到jwt.io來檢查其內容。

添加登出

最后一步是將注銷添加到MVC客戶端。

使用IdentityServer之類的身份驗證服務,僅清除本地應用程序cookie是不夠的。 另外,您還需要往返IdentityServer以清除中央單點登錄會話。

確切的協議步驟是在OpenID Connect處理程序內部實現的,只需將以下代碼添加到某個控制器即可觸發注銷:

public IActionResult Logout()
{
    return SignOut("Cookies", "oidc");
}

這將清除本地cookie,然后重定向到IdentityServer。 IdentityServer將清除其cookie,然后為用戶提供一個鏈接以返回到MVC應用程序。

進一步的實驗

如上所述,默認情況下,OpenID Connect處理程序要求配置文件范圍。 此范圍還包括名稱或網站之類的聲明。

讓我們向用戶添加這些聲明,以便IdentityServer可以將它們放入身份令牌中:

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")
            }
        }
    };
}

下次您進行身份驗證時,您的聲明頁面現在將顯示其他聲明。

隨時添加更多聲明-以及更多范圍。 您可以在OpenID Connect中間件上的Scope屬性中配置在身份驗證期間將哪些范圍發送到IdentityServer。

還值得注意的是,令牌聲明的檢索是可擴展性點-IProfileService。 由于我們使用的是AddTestUsers,因此默認情況下使用TestUserProfileService。 您可以在此處檢查源代碼以查看其工作方式。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容