IdentityServer4是ASP.NET Core 2的OpenID Connect和OAuth 2.0框架。javascript
它在您的應用程序中啓用如下功能:html
適用於全部應用程序(Web,本機,移動設備,服務)的集中登陸邏輯和工做流程。IdentityServer是OpenID Connect 的官方認證實現。前端
在多種應用程序類型上單點登陸(和退出)。html5
爲各類類型的客戶端發出API訪問令牌,例如服務器到服務器,Web應用程序,SPA和本機/移動應用程序。java
支持Azure Active Directory,Google,Facebook等外部身份提供商。這能夠保護您的應用程序免受如何鏈接到這些外部提供商的詳細信息的影響。node
最重要的部分 - IdentityServer的許多方面均可以根據您的需求進行定製。因爲IdentityServer是一個框架而不是盒裝產品或SaaS,所以您能夠編寫代碼以使系統適應您的方案。git
IdentityServer使用容許的Apache 2許可證,容許在其上構建商業產品。它也是.NET Foundation的一部分,它提供治理和法律支持。github
若是您須要幫助構建或運行您的身份平臺,請告知咱們。咱們能夠經過多種方式爲您提供幫助。web
大多數現代應用程序或多或少看起來像這樣:算法
最多見的互動是:
瀏覽器與Web應用程序通訊
Web應用程序與Web API進行通訊(有時是本身的,有時是表明用戶)
基於瀏覽器的應用程序與Web API通訊
本機應用程序與Web API通訊
基於服務器的應用程序與Web API通訊
Web API與Web API進行通訊(有時是本身的,有時是表明用戶)
一般,每一個層(前端,中間層和後端)都必須保護資源並實現身份驗證和/或受權 - 一般針對同一個用戶存儲。
將這些基本安全功能外包給安全令牌服務可防止在這些應用程序和端點之間複製該功能。
重構應用程序以支持安全令牌服務會產生如下體系結構和協議:
這種設計將安全問題分爲兩部分:
當應用程序須要知道當前用戶的身份時,須要進行身份驗證。一般,這些應用程序表明該用戶管理數據,而且須要確保該用戶只能訪問容許的數據。最多見的例子是(經典)Web應用程序 - 可是基於本機和JS的應用程序也須要身份驗證。
最多見的身份驗證協議是SAML2p,WS-Federation和OpenID Connect - SAML2p是最受歡迎和最普遍部署的。
OpenID Connect是三者中的最新產品,但被認爲是將來,由於它具備最大的現代應用潛力。它是從一開始就爲移動應用場景而構建的,旨在實現API友好。
應用程序有兩種與API通訊的基本方式 - 使用應用程序標識或委派用戶的標識。有時兩種方法都須要結合起來。
OAuth2是一種協議,容許應用程序從安全令牌服務請求訪問令牌並使用它們與API通訊。此委派下降了客戶端應用程序和API的複雜性,由於身份驗證和受權能夠集中。
OpenID Connect和OAuth 2.0很是類似 - 事實上,OpenID Connect是OAuth 2.0之上的擴展。兩個基本的安全問題,即身份驗證和API訪問,被合併爲一個協議 - 一般只須要一次往返安全令牌服務。
咱們相信,OpenID Connect和OAuth 2.0的結合是在可預見的將來保護現代應用程序的最佳方法。IdentityServer4是這兩種協議的實現,通過高度優化,能夠解決當今移動,本機和Web應用程序的典型安全問題。
IdentityServer是一箇中間件,可將符合規範的OpenID Connect和OAuth 2.0端點添加到任意ASP.NET Core應用程序中。
一般,您構建(或重用)包含登陸和註銷頁面的應用程序(而且可能贊成 - 取決於您的須要),IdentityServer中間件爲其添加必要的協議頭,以便客戶端應用程序能夠與之通訊使用那些標準協議。
託管應用程序能夠像您想要的那樣複雜,但咱們一般建議經過僅包含與身份驗證相關的UI來使攻擊面儘量小。
規範,文檔和對象模型使用您應該注意的某些術語。
IdentityServer是OpenID Connect提供程序 - 它實現OpenID Connect和OAuth 2.0協議。
不一樣的文獻對同一個角色使用不一樣的術語 - 您可能還會找到安全令牌服務,身份提供者,受權服務器,IP-STS等。
但它們徹底相同:一種向客戶發放安全令牌的軟件。
IdentityServer具備許多做業和功能 - 包括:
保護你的資源
使用本地賬戶存儲或外部身份提供程序對用戶進行身份驗證
提供會話管理和單點登陸
管理和驗證客戶端
向客戶發放身份和訪問令牌
驗證令牌
用戶是使用註冊客戶端訪問資源的人。
客戶端是從IdentityServer請求令牌的軟件 - 用於驗證用戶(請求身份令牌)或訪問資源(請求訪問令牌)。客戶端必須首先向IdentityServer註冊,而後才能請求令牌。
客戶端的示例包括Web應用程序,本機移動或桌面應用程序,SPA,服務器進程等。
您但願使用IdentityServer保護資源 - 用戶的身份數據或API。
每一個資源都有一個惟一的名稱 - 客戶端使用此名稱來指定他們但願訪問哪些資源。
身份數據 關於用戶的身份信息(也稱爲聲明),例如姓名或電子郵件地址。
API API資源表示客戶端要調用的功能 - 一般建模爲Web API,但不必定。
身份令牌表示身份驗證過程的結果。它至少包含用戶的標識符(稱爲sub aka subject聲明)以及有關用戶如何以及什麼時候進行身份驗證的信息。它能夠包含其餘身份數據。
訪問令牌容許訪問API資源。客戶端請求訪問令牌並將其轉發給API。訪問令牌包含有關客戶端和用戶(若是存在)的信息。API使用該信息來受權訪問其數據。
IdentityServer實現如下規範:
OpenID Connect Core 1.0(規範)
OpenID Connect Discovery 1.0(規範)
OpenID Connect會話管理1.0 - 草案28(規範)
OpenID Connect Front-Channel Logout 1.0 - 草案02(規範)
OpenID Connect Back-Channel Logout 1.0 - 草案04(規範)
OAuth 2.0(RFC 6749)
OAuth 2.0承載令牌使用(RFC 6750)
OAuth 2.0多種響應類型(規範)
OAuth 2.0表單後期響應模式(規範)
OAuth 2.0令牌撤銷(RFC 7009)
OAuth 2.0令牌自省(RFC 7662)
代碼交換的證實密鑰(RFC 7636)
用於客戶端身份驗證的JSON Web令牌(RFC 7523)
IdentityServer由許多nuget包組成。
包含核心IdentityServer對象模型,服務和中間件。僅包含對內存配置和用戶存儲的支持 - 但您能夠經過配置插入對其餘存儲的支持。這是其餘回購和包裝的內容。
包含一個簡單的入門UI,包括登陸,註銷和贊成頁面。
用於驗證API中令牌的ASP.NET Core身份驗證處理程序。處理程序容許在同一API中支持JWT和引用令牌。
IdentityServer的ASP.NET核心身份集成包。該軟件包提供了一個簡單的配置API,能夠爲IdentityServer用戶使用ASP.NET身份管理庫。
EntityFramework IdentityServer的核心存儲實現。此程序包爲IdentityServer中的配置和操做存儲提供EntityFramework實現。
此外,咱們將開發/臨時構建發佈到MyGet。若是要嘗試嘗試,請將如下Feed添加到Visual Studio:
https://www.myget.org/F/identity/
咱們爲IdentityServer提供了多種免費和商業支持和諮詢選項。
免費支持是基於社區的,並使用公共論壇
堆棧溢出
有愈來愈多的人使用IdentityServer來監控StackOverflow上的問題。若是時間容許,咱們也會嘗試回答儘量多的問題
您可使用此Feed訂閱全部IdentityServer4相關問題:
https://stackoverflow.com/questions/tagged/?tagnames=identityserver4&sort=newest
IdentityServer4
在提出新問題時請使用標籤
小膠質
您能夠在咱們的Gitter聊天室中與其餘IdentityServer4用戶聊天:
https://gitter.im/IdentityServer/IdentityServer4
報告錯誤
若是您認爲本身發現了錯誤或意外行爲,請在Github 問題跟蹤器上打開一個問題。咱們會盡快回復您。請理解咱們也有平常工做,可能太忙而沒法當即回覆。
在發佈以前還要檢查貢獻指南。
咱們正在圍繞身份和訪問控制架構進行諮詢,指導和定製軟件開發,特別是IdentityServer。請取得聯繫與咱們共同探討可行方案。
訓練
咱們常常圍繞現代應用的身份和訪問控制進行研討會。在這裏查看議程和即將公佈的日期 。咱們也能夠在貴公司私下進行培訓。 聯繫咱們以請求現場培訓。
Admin UI,Identity Express和SAML2p支持
咱們的合做夥伴提供了幾種商業附加產品,請訪問https://www.identityserver.com/products/。
您可使用您喜歡的客戶端庫嘗試IdentityServer4。咱們在demo.identityserver.io上有一個測試實例。在主頁面上,您能夠找到有關如何配置客戶端以及如何調用API的說明。
此外,咱們還有一個repo,能夠運行各類IdentityServer和Web API組合(IdentityServer 3和4,ASP.NET Core和Katana)。咱們使用此測試工具確保全部排列都有效。您能夠經過克隆此 repo來自行測試。
咱們對社區貢獻很是開放,但您應該遵循一些指導方針,以便咱們能夠絕不費力地處理這個問題。
最簡單的貢獻方式是打開一個問題並開始討論。而後咱們能夠決定是否以及如何實現功能或更改。若是您應該提交帶有代碼更改的pull請求,請從描述開始,只進行最小的更改並提供涵蓋這些更改的測試。
首先閱讀:成爲一名優秀的開源公民
請開始討論核心回購問題跟蹤器。
IdentityServer是針對ASP.NET Core 2構建的,可在.NET Framework 4.6.1(及更高版本)和.NET Core 2(及更高版本)上運行。
請在相應的GitHub倉庫中記錄一個新問題:
https://gitter.im/IdentityServer/IdentityServer4
在您提供任何代碼或內容以前,您須要簽署貢獻者許可協議。這是一個自動過程,將在您打開拉取請求後啓動。
注意
咱們只接受開發分支的PR。
若是您啓動貢獻項目(例如,支持Database X或Configuration Store Y),咱們很是感謝。告訴咱們,咱們能夠在咱們的文檔中發推文和連接。
咱們一般不想擁有這些貢獻庫,咱們已經很是忙於支持核心項目。
命名約定
截至2017年10月,IdentityServer4。* nuget名稱空間保留給咱們的軟件包。請使用如下命名約定:
YourProjectName.IdentityServer4
要麼
IdentityServer4.Contrib.YourProjectName
啓動新IdentityServer項目有兩種基本方法:
白手起家
從Visual Studio中的ASP.NET標識模板開始
若是您從頭開始,咱們提供了幾個幫助程序和內存存儲,所以您沒必要擔憂從一開始就存在持久性。
若是您從ASP.NET身份開始,咱們也提供了一種簡單的方法來集成它。
快速入門提供了各類常見IdentityServer方案的分步說明。他們從絕對的基礎開始,變得更加複雜 - 建議你按順序完成它們。
每一個快速入門都有一個參考解決方案 - 您能夠 在quickstarts文件夾中的IdentityServer4.Samples倉庫中找到代碼 。
屏幕截圖顯示了Visual Studio - 但這不是必需的。
建立快速入門IdentityServer
首先建立一個新的ASP.NET Core項目。
而後選擇「清空」選項。
接下來,添加IdentityServer4 nuget包:
或者,您可使用程序包管理器控制檯經過運行如下命令來添加依賴項:
「安裝包IdentityServer4」
注意
IdentityServer構建編號1.x目標ASP.NET Core 1.1,IdentityServer構建編號2.x目標ASP.NET Core 2.0。
IdentityServer使用一般的模式爲ASP.NET Core主機配置和添加服務。在ConfigureServices
所需的服務中配置並添加到DI系統。在Configure
中間件中添加到HTTP管道。
將Startup.cs
文件修改成以下所示:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentityServer()
.AddDeveloperSigningCredential();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseIdentityServer();
}
}
AddIdentityServer
在DI中註冊IdentityServer服務。它還爲運行時狀態註冊內存存儲。這對於開發方案頗有用。對於生產方案,您須要一個持久性或共享存儲,如數據庫或緩存。有關詳細信息,請參閱EntityFramework快速入門。
該AddDeveloperSigningCredential
擴展程序爲簽名令牌建立臨時密鑰材料。一樣,這可能對入門有用,但須要替換爲生產場景的一些持久性密鑰材料。有關更多信息,請參閱加密文檔。
注意
IdentityServer還沒有準備好啓動。咱們將在如下快速入門中添加所需的服務。
默認狀況下,Visual Studio使用IIS Express來託管您的Web項目。這徹底沒問題,除了您將沒法看到控制檯的實時日誌輸出。
IdentityServer普遍使用日誌記錄,而UI中的「可見」錯誤消息或返回給客戶端是故意模糊的。
咱們建議在控制檯主機中運行IdentityServer。您能夠經過在Visual Studio中切換啓動配置文件來完成此操做。每次啓動IdentityServer時也不須要啓動瀏覽器 - 您也能夠關閉它:
此外,在這些快速入門的一致URL上運行IdentityServer會頗有幫助。您還應該在上面的啓動配置文件對話框中配置此URL,而後使用http://localhost:5000/
。在上面的屏幕截圖中,您能夠看到此URL已配置。
注意
咱們建議爲IIS Express和自託管配置相同的端口。這樣,您能夠在二者之間切換,而無需修改客戶端中的任何配置。
要在啓動時選擇控制檯主機,必須在Visual Studio的啓動菜單中選擇它:
如上所述,每一個快速入門都有一個參考解決方案 - 您能夠 在quickstarts文件夾中的IdentityServer4.Samples repo中找到代碼 。
運行快速入門解決方案各個部分的最簡單方法是將啓動模式設置爲「當前選擇」。右鍵單擊解決方案並選擇「設置啓動項目」:
一般,首先啓動IdentityServer,而後啓動API,而後啓動客戶端。若是您確實想要調試,只能在調試器中運行。不然Ctrl + F5是運行項目的最佳方式。
本快速入門介紹了使用IdentityServer保護API的最基本方案。
在這種狀況下,咱們將定義一個API和一個想要訪問它的客戶端。客戶端將在IdentityServer請求訪問令牌並使用它來獲取對API的訪問權限。
範圍定義了您要保護的系統中的資源,例如API。
因爲咱們在本演練中使用內存配置 - 您只需建立一個類型的對象ApiResource
並設置適當的屬性便可。
將文件(例如Config.cs
)添加到項目中並添加如下代碼:
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("api1", "My API")
};
}
下一步是定義能夠訪問此API的客戶端。
對於此方案,客戶端將不具備交互式用戶,並將使用IdentityServer的所謂客戶端密鑰進行身份驗證。將如下代碼添加到Config.cs文件中:
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "client",
// no interactive user, use the clientid/secret for authentication
AllowedGrantTypes = GrantTypes.ClientCredentials,
// secret for authentication
ClientSecrets =
{
new Secret("secret".Sha256())
},
// scopes that client has access to
AllowedScopes = { "api1" }
}
};
}
要將IdentityServer配置爲使用範圍和客戶端定義,您須要向ConfigureServices
方法添加代碼。您可使用方便的擴展方法 - 在封面下,這些將相關的存儲和數據添加到DI系統中:
public void ConfigureServices(IServiceCollection services)
{
// configure identity server with in-memory stores, keys, clients and resources
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients());
}
就是這樣 - 若是您運行服務器並瀏覽瀏覽器 http://localhost:5000/.well-known/openid-configuration
,您應該會看到所謂的發現文檔。客戶端和API將使用它來下載必要的配置數據。
接下來,爲您的解決方案添加API。
您可使用ASP.NET Core Web API模板。一樣,咱們建議您控制端口並使用與之前配置Kestrel和啓動配置文件相同的技術。本演練假定您已將API配置爲運行http://localhost:5001
。
控制器
向API項目添加新控制器:
[Route("identity")]
[Authorize]
public class IdentityController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
}
}
稍後將使用此控制器來測試受權要求,以及經過API的眼睛可視化聲明身份。
組態
最後一步是將身份驗證服務添加到DI和身份驗證中間件到管道。這些將:
驗證傳入令牌以確保它來自受信任的頒發者
驗證令牌是否有效用於此api(aka範圍)
將IdentityServer4.AccessTokenValidation NuGet包添加到項目中。
將Startup更新爲以下所示:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore()
.AddAuthorization()
.AddJsonFormatters();
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ApiName = "api1";
});
}
public void Configure(IApplicationBuilder app)
{
app.UseAuthentication();
app.UseMvc();
}
}
AddAuthentication
將身份驗證服務添加到DI並配置"Bearer"
爲默認方案。AddIdentityServerAuthentication
將IdentityServer訪問令牌驗證處理程序添加到DI中以供身份驗證服務使用。 UseAuthentication
將身份驗證中間件添加到管道中,以便在每次調用主機時自動執行身份驗證。
若是您使用瀏覽器導航到控制器(http://localhost:5001/identity
),您應該得到401狀態代碼做爲回報。這意味着您的API須要憑據。
就是這樣,API如今受到IdentityServer的保護。
最後一步是編寫請求訪問令牌的客戶端,而後使用此令牌訪問API。爲此,請向您的解決方案添加一個控制檯項目(請參閱此處的完整代碼)。
IdentityServer的令牌端點實現OAuth 2.0協議,您可使用原始HTTP來訪問它。可是,咱們有一個名爲IdentityModel的客戶端庫,它將協議交互封裝在一個易於使用的API中。
將IdentityModel NuGet包添加到您的應用程序。
IdentityModel包括用於發現端點的客戶端庫。這樣您只須要知道IdentityServer的基地址 - 能夠從元數據中讀取實際的端點地址:
// discover endpoints from metadata
var disco = await DiscoveryClient.GetAsync("http://localhost:5000");
if (disco.IsError)
{
Console.WriteLine(disco.Error);
return;
}
接下來,您可使用TokenClient
該類來請求令牌。要建立實例,您須要傳遞令牌端點地址,客戶端ID和密碼。
接下來,您可使用該RequestClientCredentialsAsync
方法爲您的API請求令牌:
// request token
var tokenClient = new TokenClient(disco.TokenEndpoint, "client", "secret");
var tokenResponse = await tokenClient.RequestClientCredentialsAsync("api1");
if (tokenResponse.IsError)
{
Console.WriteLine(tokenResponse.Error);
return;
}
Console.WriteLine(tokenResponse.Json);
注意
將訪問令牌從控制檯複製並粘貼到jwt.io以檢查原始令牌。
最後一步是調用API。
要將訪問令牌發送到API,一般使用HTTP Authorization標頭。這是使用SetBearerToken
擴展方法完成的:
// call api
var client = new HttpClient();
client.SetBearerToken(tokenResponse.AccessToken);
var response = await client.GetAsync("http://localhost:5001/identity");
if (!response.IsSuccessStatusCode)
{
Console.WriteLine(response.StatusCode);
}
else
{
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(JArray.Parse(content));
}
輸出應以下所示:
注意
默認狀況下,訪問令牌將包含有關範圍,生命週期(nbf和exp),客戶端ID(client_id)和頒發者名稱(iss)的聲明。
本演練重點關注目前的成功之路
客戶端可以請求令牌
客戶端可使用令牌來訪問API
您如今能夠嘗試激發錯誤以瞭解系統的行爲,例如
嘗試在未運行時鏈接到IdentityServer(不可用)
嘗試使用無效的客戶端ID或機密來請求令牌
嘗試在令牌請求期間請求無效範圍
嘗試在API未運行時調用API(不可用)
不要將令牌發送到API
將API配置爲須要與令牌中的範圍不一樣的範圍
OAuth 2.0資源全部者密碼授予容許客戶端向令牌服務發送用戶名和密碼,並獲取表明該用戶的訪問令牌。
規範建議僅對「受信任」(或遺留)應用程序使用資源全部者密碼授予。通常來講,當您想要對用戶進行身份驗證並請求訪問令牌時,一般會更好地使用其中一個交互式OpenID Connect流程。
儘管如此,這種受權類型容許咱們將用戶的概念引入咱們的快速啓動IdentityServer,這就是咱們展現它的緣由。
就像資源(也稱爲範圍)和客戶端的內存存儲同樣,用戶也有一個。
注意
有關如何正確存儲和管理用戶賬戶的詳細信息,請查看基於ASP.NET身份的快速入門。
該類TestUser
表明測試用戶及其聲明。讓咱們經過在config類中添加如下代碼來建立幾個用戶:
首先將如下using語句添加到Config.cs
文件中:
using IdentityServer4.Test;
public static List<TestUser> GetUsers()
{
return new List<TestUser>
{
new TestUser
{
SubjectId = "1",
Username = "alice",
Password = "password"
},
new TestUser
{
SubjectId = "2",
Username = "bob",
Password = "password"
}
};
}
而後使用IdentityServer註冊測試用戶:
public void ConfigureServices(IServiceCollection services)
{
// configure identity server with in-memory stores, keys, clients and scopes
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetUsers());
}
該AddTestUsers
擴展方法作了幾件事情引擎蓋下
添加對資源全部者密碼授予的支持
添加對登陸UI一般使用的用戶相關服務的支持(咱們將在下一個快速入門中使用它)
添加對基於測試用戶的配置文件服務的支持(您將在下一個快速入門中瞭解更多信息)
您能夠經過更改AllowedGrantTypes
屬性來簡單地向現有客戶端添加對受權類型的支持 。若是您須要您的客戶端可以使用絕對支持的兩種受權類型。
一般,您但願爲資源全部者用例建立單獨的客戶端,將如下內容添加到客戶端配置中:
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
// other clients omitted...
// resource owner password grant client
new Client
{
ClientId = "ro.client",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets =
{
new Secret("secret".Sha256())
},
AllowedScopes = { "api1" }
}
};
}
客戶端看起來與咱們爲客戶端憑據授予所作的很是類似。主要區別在於客戶端會以某種方式收集用戶的密碼,並在令牌請求期間將其發送到令牌服務。
IdentityModel再次TokenClient
能夠在這裏提供幫助:
// request token
var tokenClient = new TokenClient(disco.TokenEndpoint, "ro.client", "secret");
var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync("alice", "password", "api1");
if (tokenResponse.IsError)
{
Console.WriteLine(tokenResponse.Error);
return;
}
Console.WriteLine(tokenResponse.Json);
Console.WriteLine("\n\n");
將令牌發送到身份API端點時,您會注意到與客戶端憑據受權相比有一個小但重要的區別。訪問令牌如今將包含sub
惟一標識用戶的聲明。經過在調用API以後檢查內容變量能夠看到這個「子」聲明,而且控制器應用程序也會在屏幕上顯示該聲明。
聲明的存在(或不存在)sub
容許API區分表明客戶的呼叫和表明用戶的呼叫。
在本快速入門中,咱們但願經過OpenID Connect協議爲咱們的IdentityServer添加對交互式用戶身份驗證的支持。
一旦到位,咱們將建立一個將使用IdentityServer進行身份驗證的MVC應用程序。
OpenID Connect所需的全部協議支持已內置於IdentityServer中。您須要爲登陸,註銷,贊成和錯誤提供必要的UI部件。
雖然外觀和精確的工做流程在每一個IdentityServer實現中可能老是不一樣,但咱們提供了一個基於MVC的示例UI,您能夠將其用做起點。
能夠在快速入門UI存儲庫中找到此UI 。您能夠克隆或下載此repo,並將控制器,視圖,模型和CSS放入IdentityServer Web應用程序中。
或者,您能夠從與IdentityServer Web應用程序相同的目錄中的命令行運行此命令,以自動執行下載:
iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/release/get.ps1'))
對於Unix / Linux:
\curl -L https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/release/get.sh | bash
添加MVC UI資產後,您還須要在DI系統和管道中將MVC添加到託管應用程序。ConfigureServices
使用AddMvc
擴展方法添加MVC :
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
// configure identity server with in-memory stores, keys, clients and scopes
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(Config.GetUsers());
}
Configure
使用UseMvc
擴展方法將MVC添加爲管道中的最後一箇中間件:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseIdentityServer();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}
有關詳細信息,請參閱快速入門UI 的自述文件。
注意
release
UI repo 的分支具備與最新穩定版本匹配的UI。該dev
分支與IdentityServer4的當前開發版本一塊兒使用。若是您正在尋找特定版本的UI - 請檢查標籤。
花一些時間檢查控制器和模型,您越瞭解它們,就越容易進行將來的修改。大多數代碼使用「功能文件夾」樣式存在於「Quickstart」文件夾中。若是此樣式不適合您,請隨意以您想要的任何方式組織代碼。
接下來,您將向您的解決方案添加MVC應用程序。使用ASP.NET Core「Web應用程序」(即MVC)模板。不要在嚮導中配置「身份驗證」設置 - 您將在此快速入門中手動執行此操做。建立項目後,將應用程序配置爲使用端口5002(有關如何執行此操做的說明,請參閱概述部分)。
要爲ID鏈接的認證支持添加到了MVC應用程序,添加如下內容ConfigureServices
中Startup
:
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.SignInScheme = "Cookies";
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ClientId = "mvc";
options.SaveTokens = true;
});
}
AddAuthentication
將身份驗證服務添加到DI。做爲主裝置來驗證用戶(經過咱們使用一個cookie "Cookies"
爲DefaultScheme
)。咱們設置爲DefaultChallengeScheme
to,"oidc"
由於當咱們須要用戶登陸時,咱們將使用OpenID Connect方案。
而後AddCookie
,咱們使用添加能夠處理cookie的處理程序。
最後,AddOpenIdConnect
用於配置執行OpenID Connect協議的處理程序。這Authority
代表咱們信任IdentityServer。而後咱們經過ClientId
。識別這個客戶。 SignInScheme
用於在OpenID Connect協議完成後使用cookie處理程序發出cookie。而且SaveTokens
用於在cookie中保留來自IdentityServer的令牌(由於稍後將須要它們)。
一樣,咱們已經關閉了JWT聲明類型映射,以容許衆所周知的聲明(例如「sub」和「idp」)流暢地經過:
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
而後要確保認證服務執行對每一個請求,加入UseAuthentication
到Configure
中Startup
:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseAuthentication();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}
應該在管道中的MVC以前添加認證中間件。
最後一步是觸發身份驗證握手。爲此,請轉到主控制器並添加[Authorize]
其中一個操做。同時修改該操做的視圖以顯示用戶的聲明,例如:
<dl>
若是您如今使用瀏覽器導航到該控制器,將嘗試重定向到IdentityServer - 這將致使錯誤,由於MVC客戶端還沒有註冊。
與OAuth 2.0相似,OpenID Connect也使用範圍概念。一樣,範圍表明您想要保護的內容以及客戶想要訪問的內容。與OAuth相比,OIDC中的範圍不表明API,而是表明用戶ID,名稱或電子郵件地址等身份數據。
經過添加新助手(in )來建立對象集合,添加對標準openid
(subject id)和profile
(名字,姓氏等)範圍的支持:Config.cs``IdentityResource
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
};
}
注意
全部標準範圍及其相應的聲明均可以在OpenID Connect 規範中找到
而後,您須要將這些標識資源添加到IdentityServer配置中Startup.cs
。使用AddInMemoryIdentityResources
您調用的擴展方法AddIdentityServer()
:
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());
}
最後一步是將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,
// where to redirect to after login
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
}
}
};
}
如今終於應該爲新的MVC客戶端作好一切準備。
經過導航到受保護的控制器操做來觸發身份驗證握手。您應該會看到重定向到IdentityServer的登陸頁面。
成功登陸後,將向用戶顯示贊成屏幕。在這裏,用戶能夠決定是否要將他的身份信息發佈到客戶端應用程序。
注意
可使用RequireConsent
客戶端對象上的屬性基於每一個客戶端關閉贊成。
..最後,瀏覽器重定向回客戶端應用程序,顯示用戶的聲明。
注意
在開發期間,您有時可能會看到一個異常,指出沒法驗證令牌。這是由於簽名密鑰材料是在運行中建立的,而且僅保留在內存中。當客戶端和IdentityServer不一樣步時會發生此異常。只需在客戶端重複操做,下次元數據遇上時,一切都應該再次正常工做。
最後一步是向MVC客戶端添加註銷。
使用IdentityServer等身份驗證服務,僅清除本地應用程序cookie是不夠的。此外,您還須要向IdentityServer進行往返以清除中央單點登陸會話。
確切的協議步驟在OpenID Connect中間件中實現,只需將如下代碼添加到某個控制器便可觸發註銷:
public async Task Logout()
{
await HttpContext.SignOutAsync("Cookies");
await HttpContext.SignOutAsync("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")
}
}
};
}
下次進行身份驗證時,您的聲明頁面如今會顯示其餘聲明。
隨意添加更多聲明 - 以及更多範圍。在Scope
對ID鏈接中間件屬性能夠在其中配置的做用域認證期間將發送到IdentityServer。
值得注意的是,對令牌聲明的檢索是一個可擴展性點 - IProfileService
。因爲咱們正在使用AddTestUsers
,TestUserProfileService
默認使用。您能夠在此處檢查源代碼 以查看其工做原理。
接下來,咱們將添加對外部認證的支持。這很是簡單,由於您真正須要的是ASP.NET Core兼容的身份驗證處理程序。
ASP.NET Core自己支持Google,Facebook,Twitter,Microsoft Account和OpenID Connect。此外,你能夠找到不少其餘的認證供應商實現在這裏。
要使用Google進行身份驗證,首先須要向他們註冊。這是在他們的開發者控制檯完成的。經過將/ signin-google路徑添加到您的基地址(例如http:// localhost:5000 / signin-google),建立一個新項目,啓用Google+ API並配置您本地IdentityServer的回調地址。
若是您在端口5000上運行 - 您只需使用下面代碼段中的客戶端ID / secret,由於這是咱們預先註冊的。
首先將Google身份驗證處理程序添加到DI。這是經過添加該代碼段完成ConfigureServices
的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());
services.AddAuthentication()
.AddGoogle("Google", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.ClientId = "434483408261-55tc8n0cs4ff1fe21ea8df2o443v2iuc.apps.googleusercontent.com";
options.ClientSecret = "3gcoTrEDPPJ0ukn_aYYT6PWo";
});
}
默認狀況下,IdentityServer專門爲外部身份驗證的結果配置cookie處理程序(使用基於常量的方案IdentityServerConstants.ExternalCookieAuthenticationScheme
)。而後,Google處理程序的配置使用該cookie處理程序。爲了更好地理解如何完成此操做,請參閱Quickstart文件夾AccountController
下的類。
如今運行MVC客戶端並嘗試進行身份驗證 - 您將在登陸頁面上看到一個Google按鈕:
身份驗證後,您能夠看到聲明如今來自Google數據。
您能夠添加其餘外部提供程序。咱們有一個雲託管的IdentityServer4 演示版,您可使用OpenID Connect進行集成。
將OpenId Connect處理程序添加到DI:
services.AddAuthentication()
.AddGoogle("Google", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.ClientId = "434483408261-55tc8n0cs4ff1fe21ea8df2o443v2iuc.apps.googleusercontent.com";
options.ClientSecret = "3gcoTrEDPPJ0ukn_aYYT6PWo";
})
.AddOpenIdConnect("oidc", "OpenID Connect", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.SignOutScheme = IdentityServerConstants.SignoutScheme;
options.Authority = "https://demo.identityserver.io/";
options.ClientId = "implicit";
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
});
如今,用戶應該可以使用雲託管的演示標識提供程序。
注意
快速入門UI自動配置外部用戶。當外部用戶首次登陸時,將建立新的本地用戶,而且全部外部聲明都將複製並與新用戶關聯。你處理這種狀況的方式徹底取決於你。也許你想首先展現一些註冊用戶界面。能夠在此處找到默認快速入門的源代碼。能夠在此處找到執行自動配置的控制器。
在以前的快速入門中,咱們探討了API訪問和用戶身份驗證。如今咱們想把這兩個部分放在一塊兒。
OpenID Connect和OAuth 2.0組合的優勢在於,您可使用單個協議和使用令牌服務進行單次交換來實現這二者。
在以前的快速入門中,咱們使用了OpenID Connect隱式流程。在隱式流程中,全部令牌都經過瀏覽器傳輸,這對於身份令牌來講是徹底正確的。如今咱們還想要一個訪問令牌。
訪問令牌比身份令牌更敏感,若是不須要,咱們不但願將它們暴露給「外部」世界。OpenID Connect包含一個名爲「混合流」的流程,它爲咱們提供了一箭雙鵰的優點,身份令牌經過瀏覽器渠道傳輸,所以客戶端能夠在進行任何更多工做以前對其進行驗證。若是驗證成功,客戶端會打開令牌服務的反向通道以檢索訪問令牌。
沒有太多必要的修改。首先,咱們但願容許客戶端使用混合流,此外咱們還但願客戶端容許執行不在用戶上下文中的服務器到服務器API調用(這與咱們的客戶端憑證快速啓動很是類似)。這是使用該AllowedGrantTypes
屬性表示的。
接下來咱們須要添加一個客戶端密鑰。這將用於檢索反向通道上的訪問令牌。
最後,咱們還讓客戶端訪問offline_access
範圍 - 這容許請求刷新令牌以實現長期存在的API訪問:
new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
ClientSecrets =
{
new Secret("secret".Sha256())
},
RedirectUris = { "http://localhost:5002/signin-oidc" },
PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api1"
},
AllowOfflineAccess = true
};
MVC客戶端的修改也不多 - ASP.NET Core OpenID Connect處理程序內置了對混合流的支持,所以咱們只須要更改一些配置值。
咱們配置ClientSecret
匹配IdentityServer的祕密。添加offline_access
和api1
範圍,並設置ResponseType
爲(這基本上意味着「使用混合流」)code id_token
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ClientId = "mvc";
options.ClientSecret = "secret";
options.ResponseType = "code id_token";
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("api1");
options.Scope.Add("offline_access");
});
當您運行MVC客戶端時,除了如今贊成屏幕要求您提供額外的API和脫機訪問範圍以外,沒有太大的區別。
OpenID Connect中間件會自動爲您保存令牌(在咱們的案例中爲身份,訪問和刷新)。這就是SaveTokens
設置的做用。
從技術上講,令牌存儲在cookie的屬性部分中。訪問它們的最簡單方法是使用Microsoft.AspNetCore.Authentication
命名空間中的擴展方法。
例如,在您的聲明視圖中:
<dt>access token</dt>
<dd>@await ViewContext.HttpContext.GetTokenAsync("access_token")</dd>
<dt>refresh token</dt>
<dd>@await ViewContext.HttpContext.GetTokenAsync("refresh_token")</dd>
要使用訪問令牌訪問API,您須要作的就是檢索令牌,並在HttpClient上設置它:
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");
}
IdentityServer旨在提供靈活性,其中一部分容許您爲用戶及其數據(包括密碼)使用您想要的任何數據庫。若是您從一個新的用戶數據庫開始,那麼ASP.NET Identity是您能夠選擇的一個選項。本快速入門展現瞭如何將Identity Identity與IdentityServer一塊兒使用。
本快速入門假設您已經完成了全部以前的快速入門。本快速入門使用ASP.NET標識的方法是從Visual Studio中的ASP.NET標識模板建立一個新項目。這個新項目將取代咱們在以前的快速入門中從頭開始構建的先前IdentityServer項目。此解決方案中的全部其餘項目(針對客戶端和API)將保持不變。
第一步是爲您的解決方案添加ASP.NET Identity的新項目。鑑於ASP.NET Identity須要大量代碼,所以使用Visual Studio中的模板是有意義的。您最終將刪除IdentityServer的舊項目(假設您正在關注其餘快速入門),可是您須要遷移幾個項目(或者按照以前的快速入門中的描述從頭開始重寫)。
首先建立一個新的「ASP.NET核心Web應用程序」項目。
而後選擇「Web應用程序模板(模型 - 視圖 - 控制器)」選項。
而後單擊「更改身份驗證」按鈕,並選擇「我的用戶賬戶」(這意味着使用ASP.NET身份):
最後,您的新項目對話框應該以下所示。完成後,單擊「肯定」以建立項目。
不要忘記修改託管(如此處所述)以在端口5000上運行。這很重要,所以現有客戶端和api項目將繼續工做。
添加IdentityServer4.AspNetIdentity
NuGet包。這取決於IdentityServer4
包,所以會自動添加爲傳遞依賴項。
儘管這是IdentityServer的新項目,但咱們仍須要與以前的快速入門相同的範圍和客戶端配置。將用於之前快速入門的配置類(在Config.cs中)複製到此新項目中。
必要的配置更改(暫時)是禁用MVC客戶端的贊成。咱們尚未複製先前IdentityServer項目的贊成代碼,因此如今對MVC客戶端進行一次修改並設置RequireConsent=false
:
new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
RequireConsent = false,
ClientSecrets =
{
new Secret("secret".Sha256())
},
RedirectUris = { "http://localhost:5002/signin-oidc" },
PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api1"
},
AllowOfflineAccess = true
}
和之前同樣,IdentityServer須要在Startup.cs中ConfigureServices
和in Configure
中配置。
ConfigureServices
這顯示了爲ASP.NET Identity生成的模板代碼,以及IdentityServer所需的附加內容(最後)。在以前的快速入門中,AddTestUsers
擴展方法用於註冊用戶,但在這種狀況下,咱們將該擴展方法替換AddAspNetIdentity
爲使用ASP.NET Identity用戶。該AddAspNetIdentity
擴展方法須要一個通用的參數,它是你的ASP.NET身份用戶類型(同一個在須要AddIdentity
從模板方法)。
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Add application services.
services.AddTransient<IEmailSender, EmailSender>();
services.AddMvc();
// configure identity server with in-memory stores, keys, clients and scopes
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryPersistedGrants()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddAspNetIdentity<ApplicationUser>();
}
注意
在使用ASP.NET標識時,在DI系統中在 ASP.NET標識以後註冊IdentityServer很是重要,由於IdentityServer會從ASP.NET標識覆蓋某些配置。
配置
這顯示了爲ASP.NET Identity生成的模板代碼,以及UseIdentityServer
替換調用的調用UseAuthentication
。
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
// app.UseAuthentication(); // not needed, since UseIdentityServer adds the authentication middleware
app.UseIdentityServer();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
鑑於這是一個新的ASP.NET Identity項目,您將須要建立數據庫。您能夠經過從項目目錄運行命令提示符並運行來執行此操做,以下所示:dotnet ef database update -c ApplicationDbContext
此時,您應該可以運行項目並在數據庫中建立/註冊用戶。啓動應用程序,而後從主頁單擊「註冊」連接:
在註冊頁面上建立一個新的用戶賬戶:
如今您擁有了一個用戶賬戶,您應該可以登陸,使用客戶端並調用API。
啓動MVC客戶端應用程序,您應該可以單擊「安全」連接以登陸。
您應該被重定向到ASP.NET Identity登陸頁面。使用新建立的用戶登陸:
登陸後,您應該跳過贊成頁面(根據咱們上面作出的更改),並當即重定向回MVC客戶端應用程序,在該應用程序中應列出您的用戶聲明。
您還應該可以單擊「使用應用程序標識調用API」來表明用戶調用API:
如今,您已使用ASP.NET Identity中的用戶登陸。
IdentityServer的先前快速入門項目提供了贊成頁面,錯誤頁面和註銷頁面。這些缺失部分的代碼能夠簡單地從以前的快速入門項目複製到此項目中。完成後,您最終能夠刪除/刪除舊的IdentityServer項目。此外,一旦完成此操做,請不要忘記RequireConsent=true
在MVC客戶端配置上從新啓用該標誌。
此快速入門的示例代碼已經爲您完成了這些步驟,所以您能夠快速開始使用全部這些功能。請享用!
本快速入門將展現如何構建JavaScript客戶端應用程序。用戶將登陸IdentityServer,使用IdentityServer發出的訪問令牌調用Web API,並註銷IdentityServer。
爲JavaScript應用程序建立一個新項目。它能夠只是一個空的Web項目,也能夠是一個空的ASP.NET Core應用程序。此快速入門將使用空的ASP.NET Core應用程序。
建立一個新的ASP.NET Core Web應用程序:
選擇「空」模板:
單擊「肯定」按鈕以建立項目。
修改託管(如此處所述)以在端口5003上運行。
鑑於該項目主要用於客戶端,咱們須要ASP.NET Core來提供構成咱們應用程序的靜態HTML和JavaScript文件。靜態文件中間件旨在實現此目的。
在方法中註冊Startup.cs中的靜態文件中間件Configure
:
public void Configure(IApplicationBuilder app)
{
app.UseDefaultFiles();
app.UseStaticFiles();
}
此中間件如今將從應用程序的〜/ wwwroot文件夾中提供靜態文件。這是咱們將放置HTML和JavaScript文件的地方。
在MVC項目中,咱們使用庫來處理OpenID Connect協議。在這個項目中,咱們須要一個相似的庫,除了一個在JavaScript中運行而且設計爲在瀏覽器中運行的庫。該OIDC客戶端庫就是這樣一個圖書館。它能夠經過NPM,Bower以及從github 直接下載。
NPM
若是要使用NPM下載oidc-client,請按照如下步驟操做:
將新的NPM包文件添加到項目中並將其命名爲package.json:
在的package.json一個補充dependency
到oidc-client
:
"dependencies": {
"oidc-client": "1.4.1"
}
保存此文件後,Visual Studio應自動將這些包還原到名爲node_modules的文件夾中:
在〜/ node_modules / oidc-client / dist文件夾中找到名爲oidc-client.js的文件,並將其複製到應用程序的〜/ wwwroot文件夾中。有更復雜的方法將NPM包複製到〜/ wwwroot,但這些技術超出了本快速入門的範圍。
接下來是將您的HTML和JavaScript文件添加到〜/ wwwroot。咱們將有兩個HTML文件和一個特定於應用程序的JavaScript文件(除了oidc-client.js庫)。在〜/ wwwroot中,添加一個名爲index.html和callback.html的HTML文件,並添加一個名爲app.js的JavaScript文件。
的index.html
這將是咱們的應用程序中的主頁。它將只包含用於登陸,註銷和調用Web API的按鈕的HTML。它還將包含<script>
標記以包含咱們的兩個JavaScript文件。它還包含<pre>
用於向用戶顯示消息的用途。
它應該以下所示:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<button id="login">Login</button>
<button id="api">Call API</button>
<button id="logout">Logout</button>
<pre id="results"></pre>
<script src="oidc-client.js"></script>
<script src="app.js"></script>
</body>
</html>
app.js
這將包含咱們的應用程序的主要代碼。第一件事是添加一個幫助函數來將消息記錄到<pre>
:
function log() {
document.getElementById('results').innerText = '';
Array.prototype.forEach.call(arguments, function (msg) {
if (msg instanceof Error) {
msg = "Error: " + msg.message;
}
else if (typeof msg !== 'string') {
msg = JSON.stringify(msg, null, 2);
}
document.getElementById('results').innerHTML += msg + '\r\n';
});
}
接下來,添加代碼以將「click」事件處理程序註冊到三個按鈕:
document.getElementById("login").addEventListener("click", login, false);
document.getElementById("api").addEventListener("click", api, false);
document.getElementById("logout").addEventListener("click", logout, false);
接下來,咱們可使用UserManager
類的OIDC客戶端庫來管理ID鏈接協議。它須要MVC Client中必需的相似配置(儘管具備不一樣的值)。添加此代碼以配置和實例化UserManager
:
var config = {
authority: "http://localhost:5000",
client_id: "js",
redirect_uri: "http://localhost:5003/callback.html",
response_type: "id_token token",
scope:"openid profile api1",
post_logout_redirect_uri : "http://localhost:5003/index.html",
};
var mgr = new Oidc.UserManager(config);
接下來,UserManager
提供getUser
API以瞭解用戶是否登陸到JavaScript應用程序。它使用JavaScript Promise
以異步方式返回結果。返回的User
對象具備profile
包含用戶聲明的屬性。添加此代碼以檢測用戶是否已登陸JavaScript應用程序:
mgr.getUser().then(function (user) {
if (user) {
log("User logged in", user.profile);
}
else {
log("User not logged in");
}
});
接下來,咱們要實現的login
,api
和logout
功能。在UserManager
提供了signinRedirect
登陸用戶,而且signoutRedirect
以註銷用戶。User
咱們在上面的代碼中得到的對象還具備access_token
可用於經過Web API進行身份驗證的屬性。在access_token
將被傳遞給經過網絡API 受權與頭承載方案。添加此代碼以在咱們的應用程序中實現這三個功能:
function login() {
mgr.signinRedirect();
}
function api() {
mgr.getUser().then(function (user) {
var url = "http://localhost:5001/identity";
var xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = function () {
log(xhr.status, JSON.parse(xhr.responseText));
}
xhr.setRequestHeader("Authorization", "Bearer " + user.access_token);
xhr.send();
});
}
function logout() {
mgr.signoutRedirect();
}
callback.html
redirect_uri
一旦用戶登陸IdentityServer,此HTML文件就是指定的頁面。它將完成與IdentityServer的OpenID Connect協議登陸握手。這個代碼所有由UserManager
咱們以前使用的類提供。登陸完成後,咱們能夠將用戶重定向回主index.html頁面。添加此代碼以完成登陸過程:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<script src="oidc-client.js"></script>
<script>
new Oidc.UserManager().signinRedirectCallback().then(function () {
window.location = "index.html";
}).catch(function (e) {
console.error(e);
});
</script>
</body>
</html>
既然客戶端應用程序已經準備就緒,咱們須要在IdentityServer中爲這個新的JavaScript客戶端定義一個配置條目。在IdentityServer項目中找到客戶端配置(在Config.cs中)。將新客戶端添加到咱們的新JavaScript應用程序的列表中。它應具備下面列出的配置:
// JavaScript Client
new Client
{
ClientId = "js",
ClientName = "JavaScript Client",
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true,
RedirectUris = { "http://localhost:5003/callback.html" },
PostLogoutRedirectUris = { "http://localhost:5003/index.html" },
AllowedCorsOrigins = { "http://localhost:5003" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"api1"
}
}
最後一點配置是在Web API項目中配置CORS。這將容許從http:// localhost:5003到http:// localhost:5001進行Ajax調用。
配置CORS
ConfigureServices
在Startup.cs中將CORS服務添加到依賴注入系統:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore()
.AddAuthorization()
.AddJsonFormatters();
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.ApiName = "api1";
});
services.AddCors(options =>
{
// this defines a CORS policy called "default"
options.AddPolicy("default", policy =>
{
policy.WithOrigins("http://localhost:5003")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
}
將CORS中間件添加到管道中Configure
:
public void Configure(IApplicationBuilder app)
{
app.UseCors("default");
app.UseAuthentication();
app.UseMvc();
}
如今您應該可以運行JavaScript客戶端應用程序:
單擊「登陸」按鈕以對用戶進行簽名。一旦用戶返回到JavaScript應用程序,您應該看到他們的我的資料信息:
而後單擊「API」按鈕以調用Web API:
最後點擊「退出」以簽署用戶。
您如今能夠開始使用IdentityServer進行登陸,註銷和驗證對Web API的調用的JavaScript客戶端應用程序。
IdentityServer旨在實現可擴展性,其中一個可擴展點是用於IdentityServer所需數據的存儲機制。本快速入門展現瞭如何配置IdentityServer以使用EntityFramework(EF)做爲此數據的存儲機制(而不是使用咱們迄今爲止使用的內存中實現)。
注意
除了手動配置EF支持外,還有一個IdentityServer模板可用於建立具備EF支持的新項目。使用建立它。有關更多信息,請參見此處dotnet new is4ef
咱們正在向數據庫移動兩種類型的數據。第一個是配置數據(資源和客戶端)。第二個是IdentityServer在使用時產生的操做數據(令牌,代碼和贊成)。這些存儲使用接口建模,咱們在IdentityServer4.EntityFramework Nuget包中提供這些接口的EF實現。
經過添加IdentityServer項目的IdentityServer4.EntityFramework Nuget包的引用開始。
鑑於EF的靈活性,您可使用任何EF支持的數據庫。對於本快速入門,咱們將使用Visual Studio附帶的SqlServer的LocalDb版本。
該IdentityServer4.EntityFramework包中包含從IdentityServer的模型映射實體類。做爲IdentityServer的車型變化,因此會在實體類IdentityServer4.EntityFramework。當您使用IdentityServer4.EntityFramework並隨着時間的推移升級時,您將負責本身的數據庫架構以及實體類更改時該架構所需的更改。管理這些更改的一種方法是使用EF遷移,此快速入門將顯示如何完成此操做。若是遷移不是您的首選項,那麼您能夠以任何您認爲合適的方式管理架構更改。
注意
爲IdentityServer4.EntityFramework中的實體維護SqlServer的SQL腳本。他們就在這裏。
除了使用EF遷移跟蹤架構更改以外,咱們還將使用它在數據庫中建立初始架構。這須要使用EF Core工具(此處有更多詳細信息)。咱們如今將添加它們,不幸的是,這必須經過手動編輯.csproj文件來完成。要經過右鍵單擊項目來編輯.csproj,而後選擇「編輯projectname.csproj」:
注意
根據您爲IdentityServer主機建立初始項目的方式,您可能已在csproj文件中配置了這些工具。若是是,您能夠跳到下一部分。
而後在結尾</ Project>元素以前添加如下代碼段:
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />
</ItemGroup>
它應該看起來像這樣:
保存並關閉文件。要測試您是否正確安裝了這些工具,能夠在與項目相同的目錄中打開命令shell並運行dotnet ef。它應該以下所示:
接下來的步驟是,以取代當前呼叫AddInMemoryClients
,AddInMemoryIdentityResources
和AddInMemoryApiResources
在ConfigureServices
在方法Startup.cs。咱們將使用如下代碼替換它們:
const string connectionString = @"Data Source=(LocalDb)\MSSQLLocalDB;database=IdentityServer4.Quickstart.EntityFramework-2.0.0;trusted_connection=yes;";
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
// configure identity server with in-memory stores, keys, clients and scopes
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddTestUsers(Config.GetUsers())
// this adds the config data from DB (clients, resources)
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
})
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
// this enables automatic token cleanup. this is optional.
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 30;
});
您可能須要將這些命名空間添加到文件中:
using Microsoft.EntityFrameworkCore;
using System.Reflection;
上面的代碼是對鏈接字符串進行硬編碼,若是您願意,能夠隨意更改。此外,調用AddConfigurationStore
和AddOperationalStore
註冊EF支持的商店實現。
傳遞給這些API的「構建器」回調函數是EF機制,容許您爲這兩個存儲中的每個配置DbContextOptionsBuilder
for DbContext
。這就是咱們的DbContext
類可使用您要使用的數據庫提供程序進行配置的方式。在這種狀況下,經過調用UseSqlServer
咱們正在使用SqlServer。您也能夠看出,這是提供鏈接字符串的位置。
「options」回調函數用於UseSqlServer
配置定義EF遷移的程序集。EF須要使用遷移來定義數據庫的模式。
注意
託管應用程序負責定義這些遷移,由於它們特定於您的數據庫和提供程序。
咱們接下來會添加遷移。
要建立遷移,請在IdentityServer項目目錄中打開命令提示符。在命令提示符下運行如下兩個命令:
dotnet ef migrations add InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/IdentityServer/PersistedGrantDb
dotnet ef migrations add InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb
它應該看起來像這樣:
您如今應該在項目中看到〜/ Data / Migrations / IdentityServer文件夾。其中包含新建立的遷移的代碼。
注意
若是您的數據庫項目是一個單獨的類庫,並修復了錯誤「沒法建立類型的對象」<您的名字> DbContext'。將「IDesignTimeDbContextFactory」的實現添加到項目中,或者參閱https://go.microsoft.com/fwlink/?linkid=851728以獲取在設計時支持的其餘模式。經過添加IDesignTimeDbContextFactory的實現,您還須要PersistedGrantDbContext和ConfigurationDbContext的工廠實現。
如今咱們已經進行了遷移,咱們能夠編寫代碼來從遷移中建立數據庫。咱們還將使用咱們在以前的快速入門中定義的內存配置數據來爲數據庫設定種子。
在Startup.cs中添加此方法以幫助初始化數據庫:
private void InitializeDatabase(IApplicationBuilder app)
{
using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
{
serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();
var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
context.Database.Migrate();
if (!context.Clients.Any())
{
foreach (var client in Config.GetClients())
{
context.Clients.Add(client.ToEntity());
}
context.SaveChanges();
}
if (!context.IdentityResources.Any())
{
foreach (var resource in Config.GetIdentityResources())
{
context.IdentityResources.Add(resource.ToEntity());
}
context.SaveChanges();
}
if (!context.ApiResources.Any())
{
foreach (var resource in Config.GetApiResources())
{
context.ApiResources.Add(resource.ToEntity());
}
context.SaveChanges();
}
}
}
而後咱們能夠從Configure
方法中調用它:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// this will do the initial DB population
InitializeDatabase(app);
// the rest of the code that was already here
// ...
}
如今,若是運行IdentityServer項目,則應建立數據庫並使用快速入門配置數據進行種子設定。您應該可以使用SQL Server Management Studio或Visual Studio來鏈接和檢查數據。
注意
上面的InitializeDatabase
輔助API能夠方便地爲數據庫設定種子,可是這種方法並不適合每次運行應用程序時執行。填充數據庫後,請考慮刪除對API的調用。
您如今應該可以運行任何現有的客戶端應用程序並登陸,獲取令牌並調用API - 全部這些都基於數據庫配置。
注意
本節中的代碼仍然依賴於Config.cs及其虛構用戶Alice和Bob。若是您的用戶列表很簡短且靜態,則調整後的Config.cs版本可能就足夠了,但您可能但願在數據庫中動態管理更大且更流暢的用戶列表。ASP.NET Identity是一個須要考慮的選項,下一節的快速入門列出了此解決方案的示例實現。
IdentityServer組織不維護這些示例。IdentityServer組織愉快地連接到社區樣本,但不能對樣本作出任何保證。請直接與做者聯繫。
https://github.com/leastprivilege/AspNetCoreSecuritySamples
此示例結合了EF和ASP.NET Identity快速入門(#6和#8)。
此示例顯示如何在與保護API的IdentityServer相同的主機中託管API。
https://github.com/brockallen/IdentityServerAndApi
IdentityServer4-mongo:與Quickstart#8 EntityFramework配置相似,但使用MongoDB配置數據。
IdentityServer4-mongo-AspIdentity:更詳細的示例基於使用ASP.NET Identity進行身份管理,使用MongoDB做爲配置數據
https://github.com/souzartn/IdentityServer4.Samples.Mongo
顯示如何使用擴展受權將外部身份驗證令牌交換到身份服務器訪問令牌
https://github.com/waqaskhan540/IdentityServerExternalAuth
基於Razor Pages的QuickStart示例由Martin Fletcher提供。
顯示可信「內部」應用程序和「外部」應用程序與.NET Core 2.0和ASP.NET Core 2.0應用程序的交互
https://github.com/BenjaminAbt/Samples.AspNetCore-IdentityServer4
演示如何使用IdentityServer4中的JWKS端點和RS256算法保護節點(Express)API。
使用更高質量的生產就緒模塊提供IdentityServer4.Samples中NodeJsApi樣本的替代方案。
https://github.com/lyphtec/idsvr4-node-jwks
IdentityServer是中間件和服務的組合。全部配置都在您的啓動類中完成。
您能夠經過調用如下方法將IdentityServer服務添加到DI系統:
public void ConfigureServices(IServiceCollection services)
{
var builder = services.AddIdentityServer();
}
您能夠選擇將選項傳入此調用。有關選項的詳細信息,請參見此
這將返回一個構建器對象,該構建器對象又有許多方便的方法來鏈接其餘服務。
AddSigningCredential
添加簽名密鑰服務,該服務爲各類令牌建立/驗證服務提供指定的密鑰材料。您能夠從證書存儲中傳入證書的a X509Certificate2
,a SigningCredential
或引用。
AddDeveloperSigningCredential
在啓動時建立臨時密鑰材料。當您沒有要使用的證書時,這僅適用於dev。生成的密鑰將保留到文件系統,以便在服務器從新啓動之間保持穩定(能夠經過傳遞禁用false
)。這解決了客戶端/ api元數據緩存在開發期間不一樣步時的問題。
AddValidationKey
添加用於驗證令牌的密鑰。它們將由內部令牌驗證器使用,並將顯示在發現文檔中。您能夠從證書存儲中傳入證書的a X509Certificate2
,a SigningCredential
或引用。這對於關鍵翻轉場景很是有用。
各類「內存中」配置API容許從內存中的配置對象列表配置IdentityServer。這些「內存中」集合能夠在宿主應用程序中進行硬編碼,也能夠從配置文件或數據庫動態加載。可是,經過設計,這些集合僅在託管應用程序啓動時建立。
使用這些配置API的目的是在原型設計,開發和/或測試時使用,在這種狀況下,不須要在運行時爲配置數據動態查詢數據庫。若是配置不多更改,則此配置樣式也可能適用於生產方案,或者若是必須更改值,則要求從新啓動應用程序並不方便。
AddInMemoryClients
基於配置對象的內存中集合的註冊IClientStore
和ICorsPolicyService
實現Client
。
AddInMemoryIdentityResources
IResourceStore
根據IdentityResource
配置對象的內存中集合註冊實現。
AddInMemoryApiResources
IResourceStore
根據ApiResource
配置對象的內存中集合註冊實現。
該TestUser
級車型的用戶,他們的憑據,並在IdentityServer索賠。使用TestUser
「內存」商店是由於它適用於原型設計,開發和/或測試。採用TestUser
在生產中不推薦使用。
AddTestUsers
TestUserStore
基於TestUser
對象集合的註冊。 TestUserStore
由默認的快速入門UI使用。還註冊IProfileService
和的實現IResourceOwnerPasswordValidator
。
AddExtensionGrantValidator
添加IExtensionGrantValidator
實現以用於擴展受權。
AddSecretParser
添加ISecretParser
用於解析客戶端或API資源憑據的實現。
AddSecretValidator
添加ISecretValidator
用於針對憑證存儲驗證客戶端或API資源憑證的實現。
AddResourceOwnerValidator
添加IResourceOwnerPasswordValidator
用於驗證資源全部者密碼憑據授予類型的用戶憑據的實現。
AddProfileService
添加IProfileService
用於鏈接到自定義用戶配置文件存儲的實現。的DefaultProfileService
類提供了依賴於驗證cookie做爲權利要求中的用於在令牌發行的惟一來源的默認實現。
AddAuthorizeInteractionResponseGenerator
添加IAuthorizeInteractionResponseGenerator
實現以在受權端點處定製邏輯,以便在必須向用戶顯示錯誤,登陸,贊成或任何其餘自定義頁面的UI時。本AuthorizeInteractionResponseGenerator
類提供了一個默認的實現,所以考慮從這個現有的類派生若是須要加強現有的行爲。
AddCustomAuthorizeRequestValidator
添加ICustomAuthorizeRequestValidator
實現以在受權端點處自定義請求參數驗證。
AddCustomTokenRequestValidator
添加ICustomTokenRequestValidator
實現以在令牌端點處自定義請求參數驗證。
AddRedirectUriValidator
添加IRedirectUriValidator
實現以自定義重定向URI驗證。
AddAppAuthRedirectUriValidator
添加符合重定向URI驗證器的「AppAuth」(適用於Native Apps的OAuth 2.0)(進行嚴格驗證,但也容許帶有隨機端口的http://127.0.0.1)。
AddJwtBearerClientAuthentication
使用JWT承載斷言添加對客戶端身份驗證的支持。
IdentityServer常用客戶端和資源配置數據。若是從數據庫或其餘外部存儲加載此數據,則頻繁從新加載相同數據可能會很昂貴。
AddInMemoryCaching
要使用下面描述的任何緩存,ICache<T>
必須在DI中註冊實現。此API註冊了ICache<T>
基於ASP.NET Core的默認內存實現MemoryCache
。
AddClientStoreCache
註冊IClientStore
裝飾器實現,該實現將維護Client
配置對象的內存緩存。緩存持續時間可在Caching
配置選項上配置IdentityServerOptions
。
AddResourceStoreCache
註冊一個IResourceStore
裝飾器實現,它將維護內存緩存IdentityResource
和ApiResource
配置對象。緩存持續時間可在Caching
配置選項上配置IdentityServerOptions
。
AddCorsPolicyCache
註冊ICorsPolicyService
裝飾器實現,該實現將維護CORS策略服務評估結果的內存緩存。緩存持續時間可在Caching
配置選項上配置IdentityServerOptions
。
能夠進一步自定義緩存:
默認緩存依賴於ICache<T>
實現。若是要自定義特定配置對象的緩存行爲,能夠在依賴項注入系統中替換此實現。
ICache<T>
自己的默認實現依賴於.NET提供的IMemoryCache
接口(和MemoryCache
實現)。若是要自定義內存中緩存行爲,能夠替換IMemoryCache
依賴項注入系統中的實現。
您須要經過調用如下方法將IdentityServer添加到管道:
public void Configure(IApplicationBuilder app)
{
app.UseIdentityServer();
}
注意
UseIdentityServer
包括打電話UseAuthentication
,所以沒有必要同時使用。
中間件沒有其餘配置。
請注意,訂單在管道中很重要。例如,您須要在實現登陸屏幕的UI框架以前添加IdentitySever。
您一般在系統中定義的第一件事是您要保護的資源。這多是您的用戶的身份信息,如我的資料數據或電子郵件地址,或訪問API。
注意
您可使用C#對象模型定義資源 - 或從數據存儲加載它們。的實施IResourceStore
與這些低級別的細節交易。對於本文檔,咱們使用內存中實現。
身份資源是用戶的用戶ID,名稱或電子郵件地址等數據。標識資源具備惟一名稱,您能夠爲其分配任意聲明類型。而後,這些聲明將包含在用戶的身份令牌中。客戶端將使用該scope
參數來請求訪問標識資源。
OpenID Connect規範指定了幾個標準身份資源。最低要求是,您爲用戶發送惟一ID提供支持 - 也稱爲主題ID。這是經過公開名爲的標準身份資源來完成的openid
:
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId()
};
}
該IdentityResources類支持的規範(OpenID的,電子郵件,我的資料,電話和地址)中定義的全部範圍。若是您想所有支持它們,能夠將它們添加到支持的身份資源列表中:
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Email(),
new IdentityResources.Profile(),
new IdentityResources.Phone(),
new IdentityResources.Address()
};
}
您還能夠定義自定義標識資源。建立一個新的IdentityResource類,爲其命名,並可選擇顯示名稱和描述,並定義在請求此資源時應將哪些用戶聲明包含在身份令牌中:
public static IEnumerable<IdentityResource> GetIdentityResources()
{
var customProfile = new IdentityResource(
name: "custom.profile",
displayName: "Custom profile",
claimTypes: new[] { "name", "email", "status" });
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
customProfile
};
}
有關身份資源設置的更多信息,請參閱參考部分。
要容許客戶端請求API的訪問令牌,您須要定義API資源,例如:
要獲取API的訪問權限,您還須要將它們註冊爲範圍。此次範圍類型是Resource類型:
public static IEnumerable<ApiResource> GetApis()
{
return new[]
{
// simple API with a single scope (in this case the scope name is the same as the api name)
new ApiResource("api1", "Some API 1"),
// expanded version if more control is needed
new ApiResource
{
Name = "api2",
// secret for using introspection endpoint
ApiSecrets =
{
new Secret("secret".Sha256())
},
// include the following using claims in access token (in addition to subject id)
UserClaims = { JwtClaimTypes.Name, JwtClaimTypes.Email },
// this API defines two scopes
Scopes =
{
new Scope()
{
Name = "api2.full_access",
DisplayName = "Full access to API 2",
},
new Scope
{
Name = "api2.read_only",
DisplayName = "Read only access to API 2"
}
}
}
};
}
有關API資源設置的更多信息,請參閱參考部分。
注意
由資源定義的用戶聲明由IProfileService擴展點加載。
客戶端表示能夠從您的身份服務器請求令牌的應用程序。
詳細信息各不相同,但您一般會爲客戶端定義如下經常使用設置:
惟一的客戶ID
若是須要的祕密
容許與令牌服務的交互(稱爲受權類型)
發送身份和/或訪問令牌的網絡位置(稱爲重定向URI)
容許客戶端訪問的範圍列表(也稱爲資源)
注意
在運行時,經過實現來檢索客戶端IClientStore
。這容許從任意數據源(如配置文件或數據庫)加載它們。對於本文檔,咱們將使用客戶端存儲的內存版本。您能夠ConfigureServices
經過AddInMemoryClients
extensions方法鏈接內存存儲。
在這種狀況下,沒有交互式用戶 - 服務(也稱爲客戶端)想要與API(aka範圍)進行通訊:
public class Clients
{
public static IEnumerable<Client> Get()
{
return new List<Client>
{
new Client
{
ClientId = "service.client",
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.ClientCredentials,
AllowedScopes = { "api1", "api2.read_only" }
}
};
}
}
此客戶端使用所謂的隱式流來從JavaScript請求身份和訪問令牌:
var jsClient = new Client
{
ClientId = "js",
ClientName = "JavaScript Client",
ClientUri = "http://identityserver.io",
AllowedGrantTypes = GrantTypes.Implicit,
AllowAccessTokensViaBrowser = true,
RedirectUris = { "http://localhost:7017/index.html" },
PostLogoutRedirectUris = { "http://localhost:7017/index.html" },
AllowedCorsOrigins = { "http://localhost:7017" },
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"api1", "api2.read_only"
}
};
交互式服務器端(或本機桌面/移動)應用程序使用混合流。此流程爲您提供最佳安全性,由於訪問令牌僅經過反向通道調用傳輸(並容許您訪問刷新令牌):
var mvcClient = new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
ClientUri = "http://identityserver.io",
AllowedGrantTypes = GrantTypes.Hybrid,
AllowOfflineAccess = true,
ClientSecrets = { new Secret("secret".Sha256()) },
RedirectUris = { "http://localhost:21402/signin-oidc" },
PostLogoutRedirectUris = { "http://localhost:21402/" },
FrontChannelLogoutUri = "http://localhost:21402/signout-oidc",
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.Email,
"api1", "api2.read_only"
},
};
爲了使IdentityServer可以表明用戶發出令牌,該用戶必須登陸IdentityServer。
使用由ASP.NET Core中的cookie身份驗證處理程序管理的cookie來跟蹤身份驗證。
IdentityServer註冊了兩個cookie處理程序(一個用於身份驗證會話,另外一個用於臨時外部cookie)。默認狀況下使用它們,若是要手動引用它們,能夠從IdentityServerConstants
類(DefaultCookieAuthenticationScheme
和ExternalCookieAuthenticationScheme
)中獲取它們的名稱。
咱們只公開這些cookie的基本設置(到期和滑動),若是您須要更多控制,您能夠註冊本身的cookie處理程序。IdentityServer使用與使用ASP.NET Core 時DefaultAuthenticateScheme
配置的cookie處理程序相匹配的cookie處理程序。AuthenticationOptions``AddAuthentication
若是您但願使用本身的cookie身份驗證處理程序,則必須本身配置它。這必須ConfigureServices
在DI(with AddIdentityServer
)中註冊IdentityServer以後完成。例如:
services.AddIdentityServer()
.AddInMemoryClients(Clients.Get())
.AddInMemoryIdentityResources(Resources.GetIdentityResources())
.AddInMemoryApiResources(Resources.GetApiResources())
.AddDeveloperSigningCredential()
.AddTestUsers(TestUsers.Users);
services.AddAuthentication("MyCookie")
.AddCookie("MyCookie", options =>
{
options.ExpireTimeSpan = ...;
});
注意
IdentityServer在內部調用兩個AddAuthentication
並AddCookie
使用自定義方案(經過常量IdentityServerConstants.DefaultCookieAuthenticationScheme
),所以要覆蓋它們,您必須在以後進行相同的調用AddIdentityServer
。
IdentityServer不爲用戶身份驗證提供任何用戶界面或用戶數據庫。這些是您但願本身提供或發展的東西。
若是您須要基本UI的起點(登陸,註銷,贊成和管理受權),您可使用咱們的快速入門UI。
快速入門UI針對內存數據庫對用戶進行身份驗證。您能夠經過訪問真實用戶存儲來替換這些位。咱們有使用ASP.NET Identity的示例。
當IdentityServer在受權端點收到請求且未對用戶進行身份驗證時,將將用戶重定向到已配置的登陸頁面。您必須經過選項上的UserInteraction
設置(默認爲)通知IdentityServer登陸頁面的路徑。將傳遞一個參數,通知您的登陸頁面,登陸完成後應重定向用戶。/account/login``returnUrl
注意
經過參數注意開放重定向攻擊returnUrl
。您應該驗證returnUrl
引用的是衆所周知的位置。請參閱API 的交互服務以驗證returnUrl
參數。
在您的登陸頁面上,您可能須要有關請求上下文的信息,以便自定義登陸體驗(例如客戶端,提示參數,IdP提示或其餘內容)。這能夠經過交互服務GetAuthorizationContextAsync
上的API得到。
在HttpContext
ASP.NET Core 上有與身份驗證相關的擴展方法,用於發出身份驗證cookie並對用戶進行簽名。使用的身份驗證方案必須與您正在使用的cookie處理程序匹配(請參見上文)。
當您簽署用戶時,您必須至少發出sub
索賠和name
索賠。IdentityServer還提供了一些SignInAsync
擴展方法HttpContext
,使其更加方便。
您還能夠選擇發出idp
聲明(針對身份提供者名稱),amr
聲明(針對所使用的身份驗證方法)和/或auth_time
聲明(針對用戶身份驗證的紀元時間)。若是您不提供這些,則IdentityServer將提供默認值。
ASP.NET Core有一種靈活的方式來處理外部身份驗證。這涉及幾個步驟。
注意
若是您使用的是ASP.NET標識,則會隱藏許多基礎技術細節。建議您還閱讀Microsoft 文檔並執行ASP.NET Identity 快速入門。
與外部提供者通訊所需的協議實現封裝在身份驗證處理程序中。一些提供商使用專有協議(例如Facebook等社交提供商),有些提供商使用標準協議,例如OpenID Connect,WS-Federation或SAML2p。
有關添加外部身份驗證和配置它的分步說明,請參閱此快速入門。
調用外部身份驗證處理程序的一個選項SignInScheme
,例如:
services.AddAuthentication()
.AddGoogle("Google", options =>
{
options.SignInScheme = "scheme of cookie handler to use";
options.ClientId = "...";
options.ClientSecret = "...";
})
登陸方案指定將臨時存儲外部認證結果的cookie處理程序的名稱,例如由外部提供者發送的聲明。這是必要的,由於在完成外部身份驗證過程以前一般會涉及一些重定向。
鑑於這是一種常見作法,IdentityServer專門爲此外部提供程序工做流注冊cookie處理程序。該方案經過IdentityServerConstants.ExternalCookieAuthenticationScheme
常數表示。若是您要使用咱們的外部cookie處理程序,那麼對於SignInScheme
上面的內容,您將賦值爲IdentityServerConstants.ExternalCookieAuthenticationScheme
常量:
services.AddAuthentication()
.AddGoogle("Google", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
options.ClientId = "...";
options.ClientSecret = "...";
})
您也能夠註冊本身的自定義cookie處理程序,以下所示:
services.AddAuthentication()
.AddCookie("YourCustomScheme")
.AddGoogle("Google", options =>
{
options.SignInScheme = "YourCustomScheme";
options.ClientId = "...";
options.ClientSecret = "...";
})
注意
對於特殊狀況,您還能夠將外部cookie機制短路並將外部用戶直接轉發到主cookie處理程序。這一般涉及處理外部處理程序上的事件,以確保您從外部標識源執行正確的聲明轉換。
您能夠經過(或使用MVC )ChallengeAsync
上的擴展方法調用外部認證處理程序。HttpContext``ChallengeResult
您一般但願將一些選項傳遞給挑戰操做,例如回調頁面的路徑和簿記提供者的名稱,例如:
var callbackUrl = Url.Action("ExternalLoginCallback");
var props = new AuthenticationProperties
{
RedirectUri = callbackUrl,
Items =
{
{ "scheme", provider },
{ "returnUrl", returnUrl }
}
};
return Challenge(provider, props);
在回調頁面上,您的典型任務是:
檢查外部提供商返回的身份。
決定如何處理該用戶。若是這是新用戶或返回用戶,則可能會有所不一樣。
新用戶在被容許以前可能須要額外的步驟和UI。
可能會建立一個連接到外部提供程序的新內部用戶賬戶。
存儲您要保留的外部聲明。
刪除臨時cookie
登陸用戶
檢查外部身份:
// read external identity from the temporary cookie
var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
if (result?.Succeeded != true)
{
throw new Exception("External authentication error");
}
// retrieve claims of the external user
var externalUser = result.Principal;
if (externalUser == null)
{
throw new Exception("External authentication error");
}
// retrieve claims of the external user
var claims = externalUser.Claims.ToList();
// try to determine the unique id of the external user - the most common claim type for that are the sub claim and the NameIdentifier
// depending on the external provider, some other claim type might be used
var userIdClaim = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject);
if (userIdClaim == null)
{
userIdClaim = claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier);
}
if (userIdClaim == null)
{
throw new Exception("Unknown userid");
}
var externalUserId = userIdClaim.Value;
var externalProvider = userIdClaim.Issuer;
// use externalProvider and externalUserId to find your user, or provision a new user
清理和登陸:
// issue authentication cookie for user
await HttpContext.SignInAsync(user.SubjectId, user.Username, provider, props, additionalClaims.ToArray());
// delete temporary cookie used during external authentication
await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
// validate return URL and redirect back to authorization endpoint or a local page
if (_interaction.IsValidReturnUrl(returnUrl) || Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
return Redirect("~/");
重定向到外部提供程序以進行登陸時,必須常常從客戶端應用程序進行往返狀態。這意味着在離開客戶端以前捕獲狀態並保留狀態,直到用戶返回到客戶端應用程序。許多協議(包括OpenID Connect)容許將某種狀態做爲參數傳遞做爲請求的一部分,而且身份提供者將在響應上返回該狀態。ASP.NET Core提供的OpenID Connect身份驗證處理程序利用了協議的這一功能,這就是它實現上述returnUrl
功能的方式。
在請求參數中存儲狀態的問題是請求URL可能變得太大(超過2000個字符的公共限制)。OpenID Connect身份驗證處理程序確實提供了一個可擴展點,用於在服務器中而不是在請求URL中存儲狀態。您能夠經過ISecureDataFormat<AuthenticationProperties>
在OpenIdConnectOptions上實現和配置它來自行實現。
幸運的是,IdentityServer爲您提供了一個實現,由IDistributedCache
DI容器中註冊的實現(例如標準MemoryDistributedCache
)支持。要使用IdentityServer提供的安全數據格式實現,只需在配置DI時調用AddOidcStateDataFormatterCache
擴展方法IServiceCollection
。若是未傳遞任何參數,則配置的全部OpenID Connect處理程序將使用IdentityServer提供的安全數據格式實現:
public void ConfigureServices(IServiceCollection services)
{
// configures the OpenIdConnect handlers to persist the state parameter into the server-side IDistributedCache.
services.AddOidcStateDataFormatterCache();
services.AddAuthentication()
.AddOpenIdConnect("demoidsrv", "IdentityServer", options =>
{
// ...
})
.AddOpenIdConnect("aad", "Azure AD", options =>
{
// ...
})
.AddOpenIdConnect("adfs", "ADFS", options =>
{
// ...
});
}
若是隻配置特定方案,則將這些方案做爲參數傳遞:
public void ConfigureServices(IServiceCollection services)
{
// configures the OpenIdConnect handlers to persist the state parameter into the server-side IDistributedCache.
services.AddOidcStateDataFormatterCache("aad", "demoidsrv");
services.AddAuthentication()
.AddOpenIdConnect("demoidsrv", "IdentityServer", options =>
{
// ...
})
.AddOpenIdConnect("aad", "Azure AD", options =>
{
// ...
})
.AddOpenIdConnect("adfs", "ADFS", options =>
{
// ...
});
}
在支持的平臺上,您可使用IdentityServer對使用Windows身份驗證的用戶進行身份驗證(例如,針對Active Directory)。當前使用如下命令託管IdentityServer時,Windows身份驗證可用:
在這兩種狀況下,使用該方案的ChallengeAsync
API 都會觸發Windows身份驗證。咱們的快速入門UI中的賬戶控制器實現了必要的邏輯。HttpContext``"Windows"
使用Kestrel時,必須運行「後面」IIS並使用IIS集成:
var host = new WebHostBuilder()
.UseKestrel()
.UseUrls("http://localhost:5000")
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
使用該WebHost.CreateDefaultBuilder
方法設置時,會自動配置紅隼WebHostBuilder
。
IIS(或IIS Express)中的虛擬目錄也必須啓用Windows並啓用匿名身份驗證。
IIS集成層將Windows身份驗證處理程序配置爲DI,能夠經過身份驗證服務調用。一般在IdentityServer中,建議禁用此自動行爲。這是在ConfigureServices
:
services.Configure<IISOptions>(iis =>
{
iis.AuthenticationDisplayName = "Windows";
iis.AutomaticAuthentication = false;
});
注意
默認狀況下,顯示名稱爲空,Windows身份驗證按鈕不會顯示在快速入門UI中。若是依賴於自動發現外部提供程序,則須要設置顯示名稱。
註銷IdentityServer就像刪除身份驗證cookie同樣簡單,可是爲了完成聯合註銷,咱們必須考慮將用戶從客戶端應用程序(甚至多是上游身份提供商)中籤名。
要刪除身份驗證cookie,只需使用SignOutAsync
擴展方法便可HttpContext
。您將須要傳遞使用的方案(IdentityServerConstants.DefaultCookieAuthenticationScheme
除非您已更改,不然提供此方案):
await HttpContext.SignOutAsync(IdentityServerConstants.DefaultCookieAuthenticationScheme);
或者您可使用IdentityServer提供的便捷擴展方法:
await HttpContext.SignOutAsync();
注意
一般,您應該提示用戶註銷(意味着須要POST),不然攻擊者可能會連接到您的註銷頁面,致使用戶自動註銷。
做爲退出流程的一部分,您須要確保客戶端應用程序被告知用戶已退出。IdentityServer支持服務器端客戶端的前端通道規範(例如MVC),服務器端客戶端的反向通道 規範(例如MVC),以及基於瀏覽器的JavaScript客戶端的會話管理規範(例如SPA,React,Angular)等)。
前端服務器端客戶端
要經過前端通道規範從服務器端客戶端應用程序註銷用戶,IdentityServer中的「已註銷」頁面必須呈現<iframe>
以通知客戶端用戶已註銷。但願收到通知的客戶端必須FrontChannelLogoutUri
設置配置值。IdentityServer跟蹤用戶已登陸的客戶端,並提供GetLogoutContextAsync
在IIdentityServerInteractionService
(詳細信息)上調用的API 。此API返回一個LogoutRequest
對象,該對象具備SignOutIFrameUrl
您已註銷的頁面必須呈現爲的屬性<iframe>
。
反向通道服務器端客戶端
要經過反向通道規範從服務器端客戶端應用程序註銷用戶SignOutIFrameUrl
,IdentityServer中的端點將自動觸發服務器到服務器調用,將簽名的註銷請求傳遞給客戶端。這意味着即便若是沒有前面通道的客戶端中,「退出」,在IdentityServer頁仍必須渲染<iframe>
到SignOutIFrameUrl
如上所述。但願收到通知的客戶端必須BackChannelLogoutUri
設置配置值。
基於瀏覽器的JavaScript客戶端
鑑於會話管理規範的設計方式,IdentityServer中沒有什麼特別的,您須要作的是通知這些客戶端用戶已註銷。可是,客戶端必須對check_session_iframe執行監視,這是由oidc-client JavaScript庫實現的。
若是客戶端應用程序啓動了註銷,則客戶端首先將用戶重定向到結束會話端點。在結束會話端點處的處理可能須要經過重定向到註銷頁面來維護一些臨時狀態(例如,客戶端的註銷後重定向uri)。此狀態可能對註銷頁面有用,而且狀態的標識符經過logoutId參數傳遞到註銷頁面。
在GetLogoutContextAsync
上的API 交互服務能夠用來加載狀態。感興趣的ShowSignoutPrompt
是ShowSignoutPrompt
指示註銷請求是否已通過身份驗證,所以不會提示用戶註銷是安全的。
默認狀況下,此狀態做爲經過logoutId值傳遞的受保護數據結構進行管理。若是您但願在結束會話端點和註銷頁面之間使用其餘一些持久性,那麼您能夠IMessageStore<LogoutMessage>
在DI中實現並註冊實現。
當用戶註銷 IdentityServer,而且他們使用外部身份提供程序登陸時,可能會將其重定向到也註銷外部提供程序。並不是全部外部提供商都支持註銷,由於它取決於它們支持的協議和功能。
要檢測是否必須將用戶重定向到外部身份提供程序以進行註銷一般是經過使用idp
在IdentityServer中發佈到cookie中的聲明來完成的。設置到此聲明中的值是AuthenticationScheme
相應的身份驗證中間件。在簽出時,諮詢此索賠以瞭解是否須要外部簽出。
因爲正常註銷工做流程已經須要清理和狀態管理,所以將用戶重定向到外部身份提供商是有問題的。而後,在IdentityServer完成正常註銷和清理過程的惟一方法是從外部身份提供程序請求在註銷後將用戶重定向回IdentityServer。並不是全部外部提供商都支持退出後重定向,由於它取決於它們支持的協議和功能。
而後,簽出時的工做流程將撤消IdentityServer的身份驗證cookie,而後重定向到請求退出後重定向的外部提供程序。退出後重定向應保持此處描述的必要簽出狀態(即logoutId
參數值)。要在外部提供程序註銷後重定向回IdentityServer,RedirectUri
應該AuthenticationProperties
在使用ASP.NET Core的SignOutAsync
API 時使用,例如:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Logout(LogoutInputModel model)
{
// build a model so the logged out page knows what to display
var vm = await _account.BuildLoggedOutViewModelAsync(model.LogoutId);
var user = HttpContext.User;
if (user?.Identity.IsAuthenticated == true)
{
// delete local authentication cookie
await HttpContext.SignOutAsync();
// raise the logout event
await _events.RaiseAsync(new UserLogoutSuccessEvent(user.GetSubjectId(), user.GetName()));
}
// check if we need to trigger sign-out at an upstream identity provider
if (vm.TriggerExternalSignout)
{
// build a return URL so the upstream provider will redirect back
// to us after the user has logged out. this allows us to then
// complete our single sign-out processing.
string url = Url.Action("Logout", new { logoutId = vm.LogoutId });
// this triggers a redirect to the external provider for sign-out
return SignOut(new AuthenticationProperties { RedirectUri = url }, vm.ExternalAuthenticationScheme);
}
return View("LoggedOut", vm);
}
一旦用戶退出外部提供程序而後重定向回來,IdentityServer的正常註銷處理應該執行,這涉及處理logoutId
和執行全部必要的清理。
聯合註銷是指用戶使用外部身份提供程序登陸IdentityServer,而後用戶經過IdentityServer未知的工做流程註銷該外部身份提供程序的狀況。當用戶註銷時,對IdentityServer進行通知將很是有用,這樣它就能夠將用戶從IdentityServer和使用IdentityServer的全部應用程序簽名。
並不是全部外部身份提供商都支持聯合註銷,但那些提供的機制將提供通知客戶端用戶已註銷的機制。此通知一般以<iframe>
來自外部身份提供商的「已註銷」頁面的請求的形式出現。而後IdentityServer必須通知其全部客戶(如討論這裏),也一般在一個請求的形式<iframe>
從內外部身份提供的<iframe>
。
使聯合註銷成爲特殊狀況(與正常註銷相比)的緣由是聯合註銷請求不是IdentityServer中的正常註銷端點。實際上,每一個外部IdentityProvider都將在IdentityServer主機中具備不一樣的端點。這是由於每一個外部身份提供者可能使用不一樣的協議,而且每一箇中間件都在不一樣的端點上進行偵聽。
全部這些因素的淨效果是沒有像正常註銷工做流那樣呈現「註銷」頁面,這意味着咱們缺乏對IdentityServer客戶端的註銷通知。咱們必須爲每一個聯合註銷端點添加代碼,以呈現必要的通知以實現聯合註銷。
幸運的是,IdentityServer已經包含此代碼。當請求進入IdentityServer和調用外部認證提供商處理,IdentityServer檢測,若是這些聯合signout要求,若是他們是它會自動呈現相同<iframe>
的這裏描述signout。簡而言之,自動支持聯合註銷。
通用架構是所謂的聯合網關。在這種方法中,IdentityServer充當一個或多個外部身份提供者的網關。
該架構具備如下優勢
您的應用程序只須要了解一個令牌服務(網關),而且不受有關鏈接到外部提供程序的全部詳細信息的影響。這也意味着您能夠添加或更改這些外部提供程序,而無需更新您的應用程序。
您控制網關(而不是某些外部服務提供商) - 這意味着您能夠對其進行任何更改,並保護您的應用程序免受外部提供程序可能對其本身的服務所作的更改。
大多數外部提供商僅支持一組固定的聲明和聲明類型 - 在中間具備網關容許對提供商的響應進行後處理以轉換/添加/修改特定於域的身份信息。
某些提供商不支持訪問令牌(例如社交提供商) - 由於網關知道您的API,它能夠根據外部身份發出訪問令牌。
某些提供商按您鏈接的應用程序數收費。網關充當外部提供程序的單個應用程序。在內部,您能夠根據須要鏈接任意數量的應用程序。
一些提供商使用專有協議或對標準協議進行專有修改 - 經過網關,您只須要處理一個地方。
強制每一個身份驗證(內部或外部)經過一個地方爲身份映射提供極大的靈活性,爲您的全部應用程序提供穩定的身份並處理新的需求
換句話說 - 擁有聯合網關可讓您對身份基礎架構進行大量控制。因爲您的用戶身份是您最重要的資產之一,咱們建議您控制網關。
咱們的快速入門UI使用瞭如下一些功能。另請參閱外部身份驗證快速入門和有關外部提供程序的文檔。
您能夠經過向IdentityServer應用程序添加身份驗證處理程序來添加對外部身份提供程序的支持。
你能夠經過調用程序查詢這些外部供應商IAuthenticationSchemeProvider
。這容許基於已註冊的外部提供程序動態呈現您的登陸頁面。
咱們的客戶端配置模型容許基於每一個客戶端限制可用的提供者(使用該IdentityProviderRestrictions
屬性)。
您還可使用EnableLocalLogin
客戶端上的屬性告訴您的UI是否應該呈現用戶名/密碼輸入。
咱們的快速啓動UI漏斗經過一個回調全部外部認證調用(見ExternalLoginCallback
的AccountController
類)。這容許單點進行後處理。
在受權請求期間,若是IdentityServer須要用戶贊成,則瀏覽器將被重定向到贊成頁面。
贊成用於容許最終用戶授予客戶端對資源(身份或API)的訪問權限。這一般僅對第三方客戶端是必需的,而且能夠在客戶端設置上按客戶端啓用/禁用。
爲了讓用戶贊成,託管應用程序必須提供贊成頁面。該快速入門UI有一個批准頁面的基本實現。
贊成頁面一般呈現當前用戶的顯示名稱,請求訪問的客戶端的顯示名稱,客戶端的徽標,有關客戶端的更多信息的連接以及客戶端請求訪問的資源列表。容許用戶代表他們的贊成應該被「記住」也是很常見的,所以未來不會再次提示同一客戶。
一旦用戶提供了贊成,贊成頁面必須通知IdentityServer贊成,而後必須將瀏覽器重定向回受權端點。
IdentityServer將returnUrl參數(可在用戶交互選項上配置)傳遞到包含受權請求參數的贊成頁面。這些參數提供了贊成頁面的上下文,能夠在交互服務的幫助下閱讀。該GetAuthorizationContextAsync
API將返回的實例AuthorizationRequest
。
可使用IClientStore
和IResourceStore
接口獲取有關客戶端或資源的其餘詳細信息。
在GrantConsentAsync
對API 的交互服務容許贊成頁面知情贊成的結果(這也可能拒絕客戶端訪問)的IdentityServer。
IdentityServer將暫時保留贊成的結果。這種持久性默認使用cookie,由於它只須要持續足夠長的時間來將結果傳回給受權端點。這種臨時持久性與用於「記住個人贊成」功能的持久性不一樣(而且受權端點持續「記住我對用戶的贊成」)。若是您但願在贊成頁面和受權重定向之間使用其餘一些持久性,那麼您能夠IMessageStore<ConsentResponse>
在DI中實現並註冊實現。
一旦贊成頁面通知IdentityServer結果,就能夠將用戶重定向回returnUrl。您的贊成頁面應經過驗證returnUrl是否有效來防止打開重定向。這能夠經過調用來完成IsValidReturnUrl
的交互服務。此外,若是GetAuthorizationContextAsync
返回非null結果,那麼您還能夠信任returnUrl有效。
IdentityServer 默認以JWT(JSON Web令牌)格式發出訪問令牌。
今天的每一個相關平臺都支持驗證JWT令牌,這裏能夠找到一個很好的JWT庫列表。熱門圖書館例如:
ASP.NET Core的JWT承載認證處理程序
Katana的JWT承載認證中間件
Katana的IdentityServer身份驗證中間件
jsonwebtoken爲的NodeJS
保護基於ASP.NET核心的API只需在DI中配置JWT承載認證處理程序,並將認證中間件添加到管道:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
// base-address of your identityserver
options.Authority = "https://demo.identityserver.io";
// name of the API resource
options.Audience = "api1";
});
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.UseAuthentication();
app.UseMvc();
}
}
咱們的身份驗證處理程序與上面的處理程序具備相同的用途(實際上它在內部使用Microsoft JWT庫),但添加了一些其餘功能:
支持JWT和參考令牌
用於引用標記的可擴展緩存
統一配置模型
範圍驗證
對於最簡單的狀況,咱們的處理程序配置看起來很是相似於上面的代碼段:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
// base-address of your identityserver
options.Authority = "https://demo.identityserver.io";
// name of the API resource
options.ApiName = "api1";
});
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.UseAuthentication();
app.UseMvc();
}
}
若是傳入令牌不是JWT,咱們的中間件將聯繫發現文檔中的內省端點以驗證令牌。因爲內省端點須要身份驗證,所以您須要提供已配置的API密鑰,例如:
.AddIdentityServerAuthentication(options =>
{
// base-address of your identityserver
options.Authority = "https://demo.identityserver.io";
// name of the API resource
options.ApiName = "api1";
options.ApiSecret = "secret";
})
一般,您不但願爲每一個傳入請求執行到內省端點的往返。中間件有一個內置緩存,您能夠像這樣啓用:
.AddIdentityServerAuthentication(options =>
{
// base-address of your identityserver
options.Authority = "https://demo.identityserver.io";
// name of the API resource
options.ApiName = "api1";
options.ApiSecret = "secret";
options.EnableCaching = true;
options.CacheDuration = TimeSpan.FromMinutes(10); // that's the default
})
處理程序將使用在DI容器中註冊的任何IDistributedCache實現(例如標準的MemoryDistributedCache)。
所述ApiName屬性檢查該令牌具備匹配觀衆(或短aud
),如權利要求。
在IdentityServer中,您還能夠將API細分爲多個範圍。若是須要該粒度,可使用ASP.NET Core受權策略系統來檢查範圍。
制定全球政策:
services
.AddMvcCore(options =>
{
// require scope1 or scope2
var policy = ScopePolicy.Create("scope1", "scope2");
options.Filters.Add(new AuthorizeFilter(policy));
})
.AddJsonFormatters()
.AddAuthorization();
制定範圍政策:
services.AddAuthorization(options =>
{
options.AddPolicy("myPolicy", builder =>
{
// require scope1
builder.RequireScope("scope1");
// and require scope2 or scope3
builder.RequireScope("scope2", "scope3");
});
});
您的身份服務器只是一個標準的ASP.NET核心應用程序,包括IdentityServer中間件。首先閱讀有關發佈和部署的官方Microsoft 文檔。
一般,您將設計IdentityServer部署以實現高可用性:
IdentityServer自己是無狀態的,不須要服務器關聯 - 可是有些數據須要在實例之間共享。
這一般包括:
資源
客戶
啓動配置,例如密鑰材料,外部提供商設置等......
存儲數據的方式取決於您的環境。在配置數據不多更改的狀況下,咱們建議使用內存存儲和代碼或配置文件。
在高度動態的環境(例如Saas)中,咱們建議使用數據庫或配置服務動態加載配置。
IdentityServer支持開箱即用的代碼配置和配置文件(請參閱此處)。對於數據庫,咱們爲基於Entity Framework Core的數據庫提供支持。
您還能夠經過實現IResourceStore
和構建本身的配置存儲IClientStore
。
另外一個重要的啓動配置是您的主要材料,請參閱此處以獲取有關密鑰材料和加密的更多詳細信息。
對於某些操做,IdentityServer須要持久性存儲來保持狀態,這包括:
發佈受權碼
發出引用和刷新令牌
存儲贊成
您可使用傳統數據庫存儲操做數據,也可使用具備Redis等持久性功能的緩存。上面提到的EF Core實現也支持運營數據。
您還能夠經過實現實現對本身的自定義存儲機制的支持IPersistedGrantStore
- 默認狀況下IdentityServer會注入內存中的版本。
ASP.NET Core自己須要共享密鑰材料來保護cookie,狀態字符串等敏感數據。請參閱此處的官方文檔。
您能夠重複使用上述持久性存儲之一,也可使用像共享文件這樣的簡單文件。
IdentityServer使用ASP.NET Core提供的標準日誌記錄工具。Microsoft 文檔有一個很好的介紹和內置日誌記錄提供程序的說明。
咱們大體遵循Microsoft使用日誌級別的指導原則:
Trace
僅供開發人員解決問題的信息。這些消息可能包含敏感的應用程序數據(如令牌),不該在生產環境中啓用。
Debug
遵循內部流程並理解爲什麼作出某些決定。在開發和調試過程當中具備短時間實用性。
Information
用於跟蹤應用程序的通常流程。這些日誌一般具備一些長期價值。
Warning
對於應用程序流中的異常或意外事件。這些可能包括錯誤或其餘不會致使應用程序中止但可能須要調查的條件。
Error
對於沒法處理的錯誤和異常。示例:協議請求的驗證失敗。
Critical
對於須要當即關注的故障。示例:缺乏商店實施,無效的密鑰材料......
咱們我的很是喜歡Serilog。試試看。
對於如下配置,您須要Serilog.AspNetCore
和Serilog.Sinks.Console
包:
public class Program
{
public static void Main(string[] args)
{
Console.Title = "IdentityServer4";
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("System", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Literate)
.CreateLogger();
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args)
{
return WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseSerilog()
.Build();
}
}
對於如下配置,您須要Serilog.Extensions.Logging
和Serilog.Sinks.Console
包:
public class Program
{
public static void Main(string[] args)
{
Console.Title = "IdentityServer4";
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("System", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Literate)
.CreateLogger();
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args)
{
return WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(builder =>
{
builder.ClearProviders();
builder.AddSerilog();
})
.Build();
}
}
日誌記錄是更低級別的「printf」樣式 - 事件表明有關IdentityServer中某些操做的更高級別信息。事件是結構化數據,包括事件ID,成功/失敗信息,類別和詳細信息。這使得查詢和分析它們變得容易,並提取可用於進一步處理的有用信息。
默認狀況下不會啓用事件 - 但能夠在ConfigureServices
方法中進行全局配置,例如:
services.AddIdentityServer(options =>
{
options.Events.RaiseSuccessEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseErrorEvents = true;
});
要發出事件,請使用IEventService
DI容器並調用RaiseAsync
方法,例如:
public async Task<IActionResult> Login(LoginInputModel model)
{
if (_users.ValidateCredentials(model.Username, model.Password))
{
// issue authentication cookie with subject ID and username
var user = _users.FindByUsername(model.Username);
await _events.RaiseAsync(new UserLoginSuccessEvent(user.Username, user.SubjectId, user.Username));
}
else
{
await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials"));
}
}
咱們的默認事件接收器只是將事件類序列化爲JSON並將其轉發到ASP.NET Core日誌系統。若是要鏈接到自定義事件存儲,請實現該IEventSink
接口並將其註冊到DI。
如下示例使用Seq發出事件:
public class SeqEventSink : IEventSink
{
private readonly Logger _log;
public SeqEventSink()
{
_log = new LoggerConfiguration()
.WriteTo.Seq("http://localhost:5341")
.CreateLogger();
}
public Task PersistAsync(Event evt)
{
if (evt.EventType == EventTypes.Success ||
evt.EventType == EventTypes.Information)
{
_log.Information("{Name} ({Id}), Details: {@details}",
evt.Name,
evt.Id,
evt);
}
else
{
_log.Error("{Name} ({Id}), Details: {@details}",
evt.Name,
evt.Id,
evt);
}
return Task.CompletedTask;
}
}
將Serilog.Sinks.Seq
包添加到主機以使上述代碼有效。
IdentityServer中定義瞭如下事件:
ApiAuthenticationFailureEvent
& ApiAuthenticationSuccessEvent
獲取內省端點上成功/失敗的API身份驗證。
ClientAuthenticationSuccessEvent
& ClientAuthenticationFailureEvent
獲取在令牌端點處成功/失敗的客戶端身份驗證。
TokenIssuedSuccessEvent
& TokenIssuedFailureEvent
獲取成功/失敗嘗試請求身份令牌,訪問令牌,刷新令牌和受權碼。
TokenIntrospectionSuccessEvent
& TokenIntrospectionFailureEvent
獲取成功的令牌內省請求。
TokenRevokedSuccessEvent
獲取成功的令牌吊銷請求。
UserLoginSuccessEvent
& UserLoginFailureEvent
成功/失敗用戶登陸的快速入門UI引起。
UserLogoutSuccessEvent
獲取成功的註銷請求。
ConsentGrantedEvent
& ConsentDeniedEvent
在贊成UI中引起。
UnhandledExceptionEvent
獲取未處理的異常。
您能夠建立本身的事件並經過咱們的基礎架構發出它們。
您須要從咱們的基Event
類派生,該基類注入活動ID,時間戳等上下文信息。您的派生類能夠添加特定於事件上下文的任意數據字段:
public class UserLoginFailureEvent : Event
{
public UserLoginFailureEvent(string username, string error)
: base(EventCategories.Authentication,
"User Login Failure",
EventTypes.Failure,
EventIds.UserLoginFailure,
error)
{
Username = username;
}
public string Username { get; set; }
}
IdentityServer依賴於幾個加密機制來完成其工做。
IdentityServer須要非對稱密鑰對來簽署和驗證JWT。此密鑰對能夠是證書/私鑰組合或原始RSA密鑰。不管如何,它必須支持帶有SHA256的RSA。
加載簽名密鑰和相應的驗證部分是經過ISigningCredentialStore
和的實現來完成的IValidationKeysStore
。若是要自定義加載密鑰,能夠實現這些接口並將其註冊到DI。
DI構建器擴展有幾種方便的方法來設置簽名和驗證密鑰 - 請參閱此處。
雖然一次只能使用一個簽名密鑰,但您能夠將多個驗證密鑰發佈到發現文檔。這對於密鑰翻轉頗有用。
翻轉一般以下所示:
您請求/建立新的密鑰材料
除了當前的驗證密鑰以外,還要發佈新的驗證密鑰。您可使用AddValidationKeys
構建器擴展方法。
全部客戶端和API如今都有機會在下次更新發現文檔的本地副本時瞭解新密鑰
在必定時間(例如24小時)以後,全部客戶端和API如今應該接受舊密鑰材料和新密鑰材料
只要你願意,就能夠保留舊的密鑰材料,也許你有須要驗證的長壽命令牌
當舊密鑰材料再也不使用時,將其退出
全部客戶端和API將在下次更新發現文檔的本地副本時「忘記」舊密鑰
這要求客戶端和API使用發現文檔,而且還具備按期刷新其配置的功能。
ASP.NET Core中的Cookie身份驗證(或MVC中的防僞)使用ASP.NET Core數據保護功能。根據您的部署方案,這可能須要其餘配置。有關更多信息,請參閱Microsoft 文檔。
咱們不強制使用HTTPS,但對於生產,它必須與IdentityServer進行每次交互。
受權類型是指定客戶端如何與IdentityServer交互的方式。OpenID Connect和OAuth 2規範定義瞭如下受權類型:
含蓄
受權碼
混合動力
客戶憑證
資源全部者密碼
刷新令牌
延期撥款
您能夠經過配置上的AllowedGrantTypes
屬性指定客戶端可使用的受權類型Client
。
能夠將客戶端配置爲使用多個受權類型(例如,用於以用戶爲中心的操做的混合和用於服務器到服務器通訊的客戶端憑證)。的GrantTypes
類能夠用來從典型交付式的組合,以挑選:
Client.AllowedGrantTypes = GrantTypes.HybridAndClientCredentials;
您也能夠手動指定受權類型列表:
Client.AllowedGrantTypes =
{
GrantType.Hybrid,
GrantType.ClientCredentials,
"my_custom_grant_type"
};
若是要經過瀏覽器通道傳輸訪問令牌,還須要在客戶端配置上明確容許:
Client.AllowAccessTokensViaBrowser = true;
注意
出於安全緣由,並不是全部受權類型組合都是容許的。請參閱下面的更多細節。
對於其他部分,簡要描述了受權類型,以及什麼時候使用它們。還建議您另外閱讀相應的規格以更好地理解差別。
這是最簡單的受權類型,用於服務器到服務器通訊 - 始終表明客戶端而不是用戶請求令牌。
使用此受權類型,您能夠向令牌端點發送令牌請求,並獲取表明客戶端的訪問令牌。客戶端一般必須使用其客戶端ID和密鑰對令牌端點進行身份驗證。
有關如何使用它的示例,請參閱「 客戶端憑據快速入門 」。
資源全部者密碼授予類型容許經過將用戶的名稱和密碼發送到令牌端點來表明用戶請求令牌。這就是所謂的「非交互式」身份驗證,一般不推薦使用。
某些遺留或第一方集成方案可能有緣由,其中此受權類型頗有用,但通常建議使用隱式或混合的交互式流來代替用戶身份驗證。
有關如何使用它的示例,請參閱資源全部者密碼快速入門。您還須要提供用戶名/密碼驗證的代碼,能夠經過實現IResourceOwnerPasswordValidator
接口來提供。您能夠在此處找到有關此界面的更多信息。
隱式受權類型針對基於瀏覽器的應用程序進行了優化。僅用於用戶身份驗證(服務器端和JavaScript應用程序),或身份驗證和訪問令牌請求(JavaScript應用程序)。
在隱式流程中,全部令牌都經過瀏覽器傳輸,所以不容許使用刷新令牌等高級功能。
該快速入門顯示了服務端的web應用程序的認證,而 這個顯示的JavaScript。
受權代碼流最初由OAuth 2指定,並提供了一種在反向通道上檢索令牌而不是瀏覽器前端通道的方法。它還支持客戶端身份驗證。
雖然這種受權類型自己是受支持的,但一般建議您將其與身份令牌結合使用,將其轉換爲所謂的混合流。混合流程爲您提供重要的額外功能,如簽名協議響應。
混合流是隱式和受權代碼流的組合 - 它使用多種受權類型的組合,最典型的是。code id_token
在混合流中,身份令牌經過瀏覽器通道傳輸,幷包含簽名協議響應以及其餘工件(如受權代碼)的簽名。這減輕了許多適用於瀏覽器通道的攻擊。成功驗證響應後,反向通道用於檢索訪問和刷新令牌。
這是但願檢索訪問令牌(也多是刷新令牌)的本機應用程序的推薦流程,用於服務器端Web應用程序和本機桌面/移動應用程序。
有關將混合流與MVC一塊兒使用的更多信息,請參閱此快速入門。
刷新令牌容許得到對API的長期訪問。
您一般但願儘量縮短訪問令牌的生命週期,但同時不但願經過對IdentityServer進行前端通道往返來請求新的令牌一次又一次地打擾用戶。
刷新令牌容許在沒有用戶交互的狀況下請求新的訪問令牌。每次客戶端刷新令牌時,都須要對IdentityServer進行(通過身份驗證的)反向通道調用。這容許檢查刷新令牌是否仍然有效,或者在此期間是否已被撤銷。
混合,受權代碼和資源全部者密碼流支持刷新令牌。要請求刷新令牌,客戶端須要offline_access
在令牌請求中包含範圍(而且必須被受權請求該範圍)。
擴展受權容許使用新的受權類型擴展令牌端點。有關詳細信息,請參閱此
禁止使用某些受權類型組合:
混合隱式和受權代碼或混合將容許從更安全的基於代碼的流的降級攻擊到隱式。
一樣存在容許受權代碼和混合代碼的問題
在某些狀況下,客戶端須要使用身份服務器進行身份驗證,例如
在令牌端點請求令牌的機密應用程序(也稱爲客戶端)
API在內省端點驗證引用令牌
爲此,您能夠將祕密列表分配給客戶端或API資源。
祕密解析和驗證是身份服務器中的可擴展點,開箱即用它支持共享機密以及經過基自己份驗證頭或POST主體傳輸共享機密。
如下代碼設置散列共享密鑰:
var secret = new Secret("secret".Sha256());
如今能夠將此祕密分配給a Client
或an ApiResource
。請注意,它們不只支持單個祕密,還支持多個祕密。這對於祕密翻轉和輪換很是有用:
var client = new Client
{
ClientId = "client",
ClientSecrets = new List<Secret> { secret },
AllowedGrantTypes = GrantTypes.ClientCredentials,
AllowedScopes = new List<string>
{
"api1", "api2"
}
};
實際上,您還能夠爲祕密分配說明和到期日期。該描述將用於記錄,以及強制執行祕密生存期的到期日期:
var secret = new Secret(
"secret".Sha256(),
"2016 secret",
new DateTime(2016, 12, 31));
您能夠將客戶端ID /機密組合做爲POST正文的一部分發送:
POST /connect/token
client_id=client1&
client_secret=secret&
...
..或做爲基自己份驗證標頭:
POST /connect/token
Authorization: Basic xxxxx
...
您可使用如下C#代碼手動建立基自己份驗證標頭:
var credentials = string.Format("{0}:{1}", clientId, clientSecret);
var headerValue = Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials));
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", headerValue);
該IdentityModel庫有一個叫作輔助類TokenClient
和IntrospectionClient
封裝認證和協議消息。
還有其餘技術來驗證客戶端,例如基於公鑰/私鑰加密。IdentityServer包括對私鑰JWT客戶機密鑰的支持(請參閱RFC 7523)。
祕密可擴展性一般包含三件事:
一個祕密的定義
一個知道如何從傳入請求中提取祕密的祕密解析器
一個祕密驗證器,知道如何根據定義驗證解析的祕密
祕密解析器和驗證器是ISecretParser
和ISecretValidator
接口的實現。要使它們可用於IdentityServer,您須要將它們註冊到DI容器,例如:
builder.AddSecretParser<ClientAssertionSecretParser>()
builder.AddSecretValidator<PrivateKeyJwtSecretValidator>()
咱們的默認私鑰JWT祕密驗證器指望完整(葉)證書做爲祕密定義的base64。而後,此證書將用於驗證自簽名JWT上的簽名,例如:
var client = new Client
{
ClientId = "client.jwt",
ClientSecrets =
{
new Secret
{
Type = IdentityServerConstants.SecretTypes.X509CertificateBase64,
Value = "MIIDATCCAe2gAwIBAgIQoHUYAquk9rBJcq8W+F0FAzAJBgUrDgMCHQUAMBIxEDAOBgNVBAMTB0RldlJvb3QwHhcNMTAwMTIwMjMwMDAwWhcNMjAwMTIwMjMwMDAwWjARMQ8wDQYDVQQDEwZDbGllbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSaY4x1eXqjHF1iXQcF3pbFrIbmNw19w/IdOQxbavmuPbhY7jX0IORu/GQiHjmhqWt8F4G7KGLhXLC1j7rXdDmxXRyVJBZBTEaSYukuX7zGeUXscdpgODLQVay/0hUGz54aDZPAhtBHaYbog+yH10sCXgV1Mxtzx3dGelA6pPwiAmXwFxjJ1HGsS/hdbt+vgXhdlzud3ZSfyI/TJAnFeKxsmbJUyqMfoBl1zFKG4MOvgHhBjekp+r8gYNGknMYu9JDFr1ue0wylaw9UwG8ZXAkYmYbn2wN/CpJl3gJgX42/9g87uLvtVAmz5L+rZQTlS1ibv54ScR2lcRpGQiQav/LAgMBAAGjXDBaMBMGA1UdJQQMMAoGCCsGAQUFBwMCMEMGA1UdAQQ8MDqAENIWANpX5DZ3bX3WvoDfy0GhFDASMRAwDgYDVQQDEwdEZXZSb290ghAsWTt7E82DjU1E1p427Qj2MAkGBSsOAwIdBQADggEBADLje0qbqGVPaZHINLn+WSM2czZk0b5NG80btp7arjgDYoWBIe2TSOkkApTRhLPfmZTsaiI3Ro/64q+Dk3z3Kt7w+grHqu5nYhsn7xQFAQUf3y2KcJnRdIEk0jrLM4vgIzYdXsoC6YO+9QnlkNqcN36Y8IpSVSTda6gRKvGXiAhu42e2Qey/WNMFOL+YzMXGt/nDHL/qRKsuXBOarIb++43DV3YnxGTx22llhOnPpuZ9/gnNY7KLjODaiEciKhaKqt/b57mTEz4jTF4kIg6BP03MUfDXeVlM1Qf1jB43G2QQ19n5lUiqTpmQkcfLfyci2uBZ8BkOhXr3Vk9HIk/xBXQ="
}
},
AllowedGrantTypes = GrantTypes.ClientCredentials,
AllowedScopes = { "api1", "api2" }
};
您能夠實現本身的祕密驗證器(或擴展咱們的祕密驗證器)來實現例如鏈信任驗證。
OAuth 2.0定義了令牌端點的標準受權類型,例如password
,authorization_code
和refresh_token
。擴展受權是一種添加對非標準令牌頒發方案(如令牌轉換,委派或自定義憑據)的支持的方法。
您能夠經過實現IExtensionGrantValidator
接口添加對其餘受權類型的支持:
public interface IExtensionGrantValidator
{
/// <summary>
/// Handles the custom grant request.
/// </summary>
/// <param name="request">The validation context.</param>
Task ValidateAsync(ExtensionGrantValidationContext context);
/// <summary>
/// Returns the grant type this validator can deal with
/// </summary>
/// <value>
/// The type of the grant.
/// </value>
string GrantType { get; }
}
該ExtensionGrantValidationContext
對象使您能夠訪問:
傳入令牌請求 - 衆所周知的驗證值,以及任何自定義值(經過Raw
集合)
結果 - 錯誤或成功
自定義響應參數
要註冊擴展受權,請將其添加到DI:
builder.AddExtensionGrantValidator<MyExtensionsGrantValidator>();
想象一下如下場景 - 前端客戶端使用經過交互流(例如混合流)獲取的令牌調用中間層API。此中間層API(API 1)如今但願表明交互式用戶調用後端API(API 2):
換句話說,中間層API(API 1)須要包含用戶身份的訪問令牌,但須要具備後端API(API 2)的範圍。
注意
您可能據說過窮人表明團這一術語,前端的訪問令牌只是轉發到後端。這有一些缺點,例如API 2如今必須接受API 1範圍,這將容許用戶直接調用API 2。此外 - 您可能但願在令牌中添加一些特定於委託的聲明,例如,呼叫路徑是經過API 1的事實。
實施擴展受權
前端會將令牌發送到API 1,如今須要在IdentityServer上使用API 2的新令牌交換此令牌。
在線上,對交換的令牌服務的調用可能以下所示:
POST /connect/token
grant_type=delegation&
scope=api2&
token=...&
client_id=api1.client
client_secret=secret
擴展受權驗證程序的工做是經過驗證傳入令牌並返回表示新令牌的結果來處理該請求:
public class DelegationGrantValidator : IExtensionGrantValidator
{
private readonly ITokenValidator _validator;
public DelegationGrantValidator(ITokenValidator validator)
{
_validator = validator;
}
public string GrantType => "delegation";
public async Task ValidateAsync(ExtensionGrantValidationContext context)
{
var userToken = context.Request.Raw.Get("token");
if (string.IsNullOrEmpty(userToken))
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
return;
}
var result = await _validator.ValidateAccessTokenAsync(userToken);
if (result.IsError)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
return;
}
// get user's identity
var sub = result.Claims.FirstOrDefault(c => c.Type == "sub").Value;
context.Result = new GrantValidationResult(sub, GrantType);
return;
}
}
不要忘記在DI上註冊驗證器。
註冊委託客戶端
您須要在IdentityServer中進行客戶端註冊,以容許客戶端使用此新的擴展受權,例如:
var client = new client
{
ClientId = "api1.client",
ClientSecrets = new List<Secret>
{
new Secret("secret".Sha256())
},
AllowedGrantTypes = { "delegation" },
AllowedScopes = new List<string>
{
"api2"
}
}
調用令牌端點
在API 1中,您如今能夠本身構建HTTP有效內容,或使用IdentityModel幫助程序庫:
public async Task<TokenResponse> DelegateAsync(string userToken)
{
var payload = new
{
token = userToken
};
// create token client
var client = new TokenClient(disco.TokenEndpoint, "api1.client", "secret");
// send custom grant to token endpoint, return response
return await client.RequestCustomGrantAsync("delegation", "api2", payload);
}
如今TokenResponse.AccessToken
將包含委託訪問令牌。
若是要使用OAuth 2.0資源全部者密碼憑據受權(aka password
),則須要實現並註冊IResourceOwnerPasswordValidator
接口:
public interface IResourceOwnerPasswordValidator
{
/// <summary>
/// Validates the resource owner password credential
/// </summary>
/// <param name="context">The context.</param>
Task ValidateAsync(ResourceOwnerPasswordValidationContext context);
}
在上下文中,您將找到已解析的協議參數,如UserName
和Password
,以及原始請求,若是您想查看其餘輸入數據。
而後,您的工做是實施密碼驗證並相應地設置Result
上下文。請參閱GrantValidationResult文檔
因爲訪問令牌的生命週期有限,所以刷新令牌容許在沒有用戶交互的狀況下請求新的訪問令牌。
如下流程支持刷新令牌:受權代碼,混合和資源全部者密碼憑據流。須要明確受權客戶端經過設置AllowOfflineAccess
來請求刷新令牌true
。
AbsoluteRefreshTokenLifetime
刷新令牌的最長生命週期,以秒爲單位。默認爲2592000秒/ 30天。零容許刷新令牌,當僅在SlidingRefreshTokenLifetime傳遞後使用時過時。RefreshTokenExpiration = Sliding
SlidingRefreshTokenLifetime
刷新令牌的生命週期以秒爲單位。默認爲1296000秒/ 15天
RefreshTokenUsage
ReUse
刷新令牌時刷新令牌句柄將保持不變OneTime
刷新令牌時將更新刷新令牌句柄
RefreshTokenExpiration
Absolute
刷新令牌將在固定時間點到期(由AbsoluteRefreshTokenLifetime指定)Sliding
刷新令牌時,將刷新刷新令牌的生命週期(按SlidingRefreshTokenLifetime中指定的數量)。生命週期不會超過AbsoluteRefreshTokenLifetime。
UpdateAccessTokenClaimsOnRefresh
獲取或設置一個值,該值指示是否應在刷新令牌請求上更新訪問令牌(及其聲明)。
訪問令牌能夠有兩種形式 - 自包含或參考。
JWT令牌將是一個自包含的訪問令牌 - 它是一個帶有聲明和過時的受保護數據結構。一旦API瞭解了密鑰材料,它就能夠驗證自包含的令牌,而無需與發行者進行通訊。這使得JWT難以撤銷。它們將一直有效,直到它們過時。
使用引用令牌時 - IdentityServer會將令牌的內容存儲在數據存儲中,而且只會將此令牌的惟一標識符發回給客戶端。接收此引用的API必須打開與IdentityServer的反向通道通訊以驗證令牌。
您可使用如下設置切換客戶端的令牌類型:
client.AccessTokenType = AccessTokenType.Reference;
IdentityServer提供了OAuth 2.0內省規範的實現,該規範容許API取消引用令牌。您可使用咱們的專用內省中間件 或使用身份服務器身份驗證中間件,它能夠驗證JWT和引用令牌。
內省端點須要身份驗證 - 由於內省端點的客戶端是API,您能夠在如下位置配置祕密ApiResource
:
var api = new ApiResource("api1")
{
ApiSecrets = { new Secret("secret".Sha256()) }
}
有關如何爲API配置IdentityServer身份驗證中間件的詳細信息,請參閱此處。
IdentityServer中的許多端點將經過基於JavaScript的客戶端的Ajax調用進行訪問。鑑於IdentityServer最有可能託管在與這些客戶端不一樣的源上,這意味着須要配置跨源資源共享(CORS)。
配置CORS的一種方法是AllowedCorsOrigins
在客戶端配置上使用該集合。只需將客戶端的原點添加到集合中,IdentityServer中的默認配置將查詢這些值以容許來自源的跨源調用。
注意
配置CORS時,請務必使用原點(不是URL)。例如:https://foo:123/
是一個URL,而是https://foo:123
一個原點。
若是您使用咱們提供的「內存中」或基於EF的客戶端配置,則將使用此默認CORS實現。若是您定義本身的IClientStore
,那麼您將須要實現本身的自定義CORS策略服務(見下文)。
IdentityServer容許託管應用程序實現ICorsPolicyService
徹底控制CORS策略。
要實現的單一方法是:。若是容許原點則返回,不然返回。Task<bool> IsOriginAllowedAsync(string origin)``true``false
實現後,只需在DI中註冊實現,而後IdentityServer將使用您的自定義實現。
DefaultCorsPolicyService
若是您只是但願硬編碼一組容許的原點,那麼ICorsPolicyService
可使用一個預先構建的實現調用DefaultCorsPolicyService
。這將被配置爲DI單身,並以其硬編碼的AllowedOrigins
收集,或設置標誌AllowAll
,以true
容許全部的起源。例如,在ConfigureServices
:
var cors = new DefaultCorsPolicyService(_loggerFactory.CreateLogger<DefaultCorsPolicyService>())
{
AllowedOrigins = { "https://foo", "https://bar" }
};
services.AddSingleton<ICorsPolicyService>(cors);
注意
AllowAll
謹慎使用。
IdentityServer使用ASP.NET Core的CORS中間件來提供其CORS實現。託管IdentityServer的應用程序可能還須要CORS用於本身的自定義端點。一般,二者應該在同一個應用程序中一塊兒工做。
您的代碼應使用ASP.NET Core中記錄的CORS功能,而不考慮IdentityServer。這意味着您應該定義策略並正常註冊中間件。若是您的應用程序定義了策略ConfigureServices
,那麼這些策略應該繼續在您使用它們的相同位置(在您配置CORS中間件的位置或在EnableCors
控制器代碼中使用MVC 屬性的位置)。相反,若是您使用CORS中間件(經過策略構建器回調)定義內聯策略,那麼它也應該繼續正常工做。
在您使用ASP.NET Core CORS服務和IdentityServer之間可能存在衝突的一種狀況是,若是您決定建立自定義ICorsPolicyProvider
。鑑於ASP.NET Core的CORS服務和中間件的設計,IdentityServer實現了本身的自定義ICorsPolicyProvider
並將其註冊到DI系統中。幸運的是,IdentityServer實現旨在使用裝飾器模式來包裝ICorsPolicyProvider
已在DI中註冊的任何現有模式 。這意味着你也能夠實現ICorsPolicyProvider
,但它只須要在DI中的IdentityServer以前註冊(例如,在ConfigureServices
)。
能夠在https://baseaddress/.well-known/openid-configuration找到發現文檔。它包含有關IdentityServer的端點,密鑰材料和功能的信息。
默認狀況下,全部信息都包含在發現文檔中,但經過使用配置選項,您能夠隱藏各個部分,例如:
services.AddIdentityServer(options =>
{
options.Discovery.ShowIdentityScopes = false;
options.Discovery.ShowApiScopes = false;
options.Discovery.ShowClaims = false;
options.Discovery.ShowExtensionGrantTypes = false;
});
您能夠向發現文檔添加自定義條目,例如:
services.AddIdentityServer(options =>
{
options.Discovery.CustomEntries.Add("my_setting", "foo");
options.Discovery.CustomEntries.Add("my_complex_setting",
new
{
foo = "foo",
bar = "bar"
});
});
當您添加以〜開頭的自定義值時,它將擴展到IdentityServer基址如下的絕對路徑,例如:
options.Discovery.CustomEntries.Add("my_custom_endpoint", "~/custom");
若是要徹底控制發現(和jwks)文檔的呈現,能夠實現IDiscoveryResponseGenerator
接口(或從咱們的默認實現派生)。
您能夠向託管IdentityServer4的應用程序添加更多API端點。
您一般但願經過它們所託管的IdentityServer實例來保護這些API。這不是問題。只需將令牌驗證處理程序添加到主機(請參閱此處):
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
// details omitted
services.AddIdentityServer();
services.AddAuthentication()
.AddIdentityServerAuthentication("token", isAuth =>
{
isAuth.Authority = "base_address_of_identityserver";
isAuth.ApiName = "name_of_api";
});
}
在您的API上,您須要添加[Authorize]
屬性並顯式引用您要使用的身份驗證方案(token
在此示例中,您能夠選擇您喜歡的任何名稱):
public class TestController : ControllerBase
{
[Route("test")]
[Authorize(AuthenticationSchemes = "token")]
public IActionResult Get()
{
var claims = User.Claims.Select(c => new { c.Type, c.Value }).ToArray();
return Ok(new { message = "Hello API", claims });
}
}
若是要從瀏覽器調用該API,則還須要配置CORS(請參閱此處)。
若是須要,您還能夠將端點添加到發現文檔中,例如:
services.AddIdentityServer(options =>
{
options.Discovery.CustomEntries.Add("custom_endpoint", "~/api/custom");
})
除了對OpenID Connect和OAuth 2.0的內置支持以外,IdentityServer4還容許添加對其餘協議的支持。
您能夠將這些附加協議端點添加爲中間件或使用例如MVC控制器。在這兩種狀況下,您均可以訪問ASP.NET Core DI系統,該系統容許重用咱們的內部服務,例如訪問客戶端定義或密鑰材料。
能夠在此處找到添加WS-Federation支持的示例。
身份驗證請求一般以下所示:
身份驗證請求到達協議端點
協議端點執行輸入驗證
重定向到登陸頁面,返回URL設置回協議端點(若是用戶是匿名的)
經過訪問當前請求詳細信息 IIdentityServerInteractionService
用戶身份驗證(本地或經過外部身份驗證中間件)登陸用戶重定向回協議端點
建立協議響應(令牌建立和重定向回客戶端)
要實現上述工做流程,須要與IdentityServer創建一些交互點。
訪問配置並重定向到登陸頁面
您能夠經過將IdentityServerOptions
類注入代碼來訪問IdentityServer配置。這個,例如具備登陸頁面的配置路徑:
var returnUrl = Url.Action("Index");
returnUrl = returnUrl.AddQueryString(Request.QueryString.Value);
var loginUrl = _options.UserInteraction.LoginUrl;
var url = loginUrl.AddQueryString(_options.UserInteraction.LoginReturnUrlParameter, returnUrl);
return Redirect(url);
登陸頁面與當前協議請求之間的交互
所述IIdentityServerInteractionService
支撐件轉動一個協議返回URL成解析和驗證上下文對象:
var context = await _interaction.GetAuthorizationContextAsync(returnUrl);
默認狀況下,交互服務僅瞭解OpenID Connect協議消息。要擴展支持,您能夠本身編寫IReturnUrlParser
:
public interface IReturnUrlParser
{
bool IsValidReturnUrl(string returnUrl);
Task<AuthorizationRequest> ParseAsync(string returnUrl);
}
..而後在DI中註冊解析器:
builder.Services.AddTransient<IReturnUrlParser, WsFederationReturnUrlParser>();
這容許登陸頁面獲取客戶端配置和其餘協議參數等信息。
訪問用於建立協議響應的配置和密鑰材料
經過將IKeyMaterialService
代碼注入到代碼中,您能夠訪問配置的簽名憑據和驗證密鑰:
工具
該IdentityServerTools班是爲IdentityServer編寫擴展代碼時,你可能須要有效的內部工具的集合。要使用它,請將其注入代碼,例如控制器:
public MyController(IdentityServerTools tools)
{
_tools = tools;
}
該IssueJwtAsync方法容許使用IdentityServer令牌建立引擎建立JWT令牌。這IssueClientJwtAsync是用於爲服務器到服務器通訊建立令牌的簡單版本(例如,當您必須從代碼中調用受IdentityServer保護的API時):
public async Task<IActionResult> MyAction()
{
var token = await _tools.IssueClientJwtAsync(
clientId: "client_id",
lifetime: 3600,
audiences: new[] { "backend.api" });
// more code
}var credential = await _keys.GetSigningCredentialsAsync();
var key = credential.Key as Microsoft.IdentityModel.Tokens.X509SecurityKey;
var descriptor = new SecurityTokenDescriptor
{
AppliesToAddress = result.Client.ClientId,
Lifetime = new Lifetime(DateTime.UtcNow, DateTime.UtcNow.AddSeconds(result.Client.IdentityTokenLifetime)),
ReplyToAddress = result.Client.RedirectUris.First(),
SigningCredentials = new X509SigningCredentials(key.Certificate, result.RelyingParty.SignatureAlgorithm, result.RelyingParty.DigestAlgorithm),
Subject = outgoingSubject,
TokenIssuerName = _contextAccessor.HttpContext.GetIdentityServerIssuerUri(),
TokenType = result.RelyingParty.TokenType
};
發現端點可用於檢索有關IdentityServer的元數據 - 它返回諸如頒發者名稱,密鑰材料,支持的範圍等信息。有關詳細信息,請參閱規範。
發現端點可經過/.well-known/openid-configuration相對於基地址得到,例如:
https://demo.identityserver.io/.well-known/openid-configuration
注意
您可使用IdentityModel客戶端庫以編程方式從.NET代碼訪問發現端點。有關更多信息,請查看IdentityModel 文檔。
受權端點可用於經過瀏覽器請求令牌或受權碼。此過程一般涉及最終用戶的身份驗證和可選的贊成。
注意
IdentityServer支持OpenID Connect和OAuth 2.0受權請求參數的子集。有關完整列表,請參見此處。
client_id
客戶的標識符(必填)。
scope
一個或多個註冊範圍(必填)
redirect_uri
必須與該客戶端容許的重定向URI之一徹底匹配(必需)
response_type
id_token
請求身份令牌(僅容許身份範圍)token
請求訪問令牌(僅容許資源範圍)id_token token
請求身份令牌和訪問令牌code
請求受權碼code id_token
請求受權代碼和身份令牌code id_token token
請求受權代碼,身份令牌和訪問令牌
response_mode
form_post
將令牌響應做爲表單發送而不是片斷編碼重定向(可選)
state
identityserver將回顯令牌響應的狀態值,這是客戶端和提供者之間的往返狀態,關聯請求和響應以及CSRF /重放保護。(推薦的)
nonce
identityserver將回顯身份令牌中的nonce值,這是爲了重放保護)經過隱式受權對身份令牌是必需的。
prompt
none
請求期間不會顯示任何UI。若是這是不可能的(例如,由於用戶必須登陸或贊成),則返回錯誤login
即便用戶已登陸並具備有效會話,也會顯示登陸UI
code_challenge
發送PKCE的代碼質詢
code_challenge_method
plain
表示挑戰是使用純文本(不推薦) S256
表示使用SHA256對挑戰進行哈希處理
login_hint
可用於預先填寫登陸頁面上的用戶名字段
ui_locales
提供有關登陸UI所需顯示語言的提示
max_age
若是用戶的登陸會話超過最大年齡(以秒爲單位),將顯示登陸UI
acr_values
容許傳遞額外的身份驗證相關信息 - 身份服務器特殊狀況下面的私有acr_values:idp:name_of_idp
繞過login / home領域屏幕並將用戶直接轉發到選定的身份提供者(若是容許每一個客戶端配置)tenant:name_of_tenant
可用於將租戶名稱傳遞給登陸UI
例
GET /connect/authorize?
client_id=client1&
scope=openid email api1&
response_type=id_token token&
redirect_uri=https://myapp/callback&
state=abc&
nonce=xyz
(刪除了URL編碼,並添加了換行符以提升可讀性)
注意
您可使用IdentityModel客戶端庫以編程方式建立受權請求.NET代碼。有關更多信息,請查看IdentityModel 文檔。
令牌端點可用於以編程方式請求令牌。它支持password
,authorization_code
,client_credentials
和refresh_token
補助的類型)。此外,能夠擴展令牌端點以支持擴展受權類型。
注意
IdentityServer支持OpenID Connect和OAuth 2.0令牌請求參數的子集。有關完整列表,請參見此處。
client_id
客戶標識符(必填)
client_secret
客戶端密鑰能夠在帖子正文中,也能夠做爲基自己份驗證標頭。可選的。
grant_type
authorization_code
,client_credentials
,password
,refresh_token
或自定義
scope
一個或多個註冊範圍。若是未指定,將發出全部明確容許範圍的標記。
redirect_uri
authorization_code
受權類型所需
code
受權碼(authorization_code
受權類型所需)
code_verifier
PKCE證實密鑰
username
資源全部者用戶名(password
授予類型所需)
password
資源全部者密碼(password
授予類型所需)
acr_values
容許爲password
受權類型傳遞額外的身份驗證相關信息- identityserver特殊狀況下面的專有acr_values:idp:name_of_idp
繞過login / home領域屏幕並將用戶直接轉發到選定的身份提供者(若是容許每一個客戶端配置)tenant:name_of_tenant
可用於將租戶名稱傳遞給令牌端點
refresh_token
刷新令牌(refresh_token
授予類型所需)
POST /connect/token
client_id=client1&
client_secret=secret&
grant_type=authorization_code&
code=hdh922&
redirect_uri=https://myapp.com/callback
(爲了便於閱讀,刪除了表格編碼並添加了換行符)
注意
您可使用IdentityModel客戶端庫以編程方式從.NET代碼訪問令牌端點。有關更多信息,請查看IdentityModel 文檔。
UserInfo端點可用於檢索有關用戶的身份信息(請參閱規範)。
調用者須要發送表明用戶的有效訪問令牌。根據授予的範圍,UserInfo端點將返回映射的聲明(至少須要openid做用域)。
GET /connect/userinfo
Authorization: Bearer <access_token>
HTTP/1.1 200 OK
Content-Type: application/json
{
"sub": "248289761001",
"name": "Bob Smith",
"given_name": "Bob",
"family_name": "Smith",
"role": [
"user",
"admin"
]
}
注意
您可使用IdentityModel客戶端庫以編程方式從.NET代碼訪問userinfo端點。有關更多信息,請查看IdentityModel 文檔。
內省端點是RFC 7662的實現。
它可用於驗證引用令牌(若是消費者不支持適當的JWT或加密庫,則可使用JWT)。內省端點須要身份驗證 - 由於內省端點的客戶端是API,您能夠在上配置密碼ApiResource
。
POST /connect/introspect
Authorization: Basic xxxyyy
token=<token>
成功的響應將返回狀態代碼200以及活動或非活動令牌:
{
"active": true,
"sub": "123"
}
未知或過時的令牌將被標記爲無效:
{
"active": false,
}
無效請求將返回400,未受權請求401。
注意
您可使用IdentityModel客戶端庫以編程方式從.NET代碼訪問內省端點。有關更多信息,請查看IdentityModel 文檔。
此端點容許撤消訪問令牌(僅限引用令牌)和刷新令牌。它實現了令牌撤銷規範(RFC 7009)。
token
要撤銷的令牌(必填)
token_type_hint
或者access_token
或refresh_token
(可選)
POST /connect/revocation HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
token=45ghiukldjahdnhzdauz&token_type_hint=refresh_token
注意
您可使用IdentityModel客戶端庫以編程方式從.NET代碼訪問吊銷端點。有關更多信息,請查看IdentityModel 文檔。
結束會話端點可用於觸發單點註銷(請參閱規範)。
要使用結束會話端點,客戶端應用程序會將用戶的瀏覽器重定向到結束會話URL。用戶在會話期間經過瀏覽器登陸的全部應用程序均可以參與註銷。
注意
終端會話端點的URL可經過發現端點得到。
id_token_hint
當用戶被重定向到端點時,系統會提示他們是否真的想要註銷。發送從身份驗證收到的原始id_token的客戶端能夠繞過此提示。這是做爲查詢的字符串參數傳遞的id_token_hint
。
post_logout_redirect_uri
若是id_token_hint
傳遞了有效,則客戶端也能夠發送post_logout_redirect_uri
參數。這可用於容許用戶在註銷後重定向回客戶端。該值必須與客戶端預先配置的PostLogoutRedirectUris(客戶端文檔)之一匹配。
州
若是post_logout_redirect_uri
傳遞了有效,則客戶端也能夠發送state
參數。在用戶重定向回客戶端後,這將做爲查詢字符串參數返回給客戶端。這一般由客戶端用於跨重定向的往返狀態。
GET /connect/endsession?id_token_hint=eyJhbGciOiJSUzI1NiIsImtpZCI6IjdlOGFkZmMzMjU1OTEyNzI0ZDY4NWZmYmIwOThjNDEyIiwidHlwIjoiSldUIn0.eyJuYmYiOjE0OTE3NjUzMjEsImV4cCI6MTQ5MTc2NTYyMSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo1MDAwIiwiYXVkIjoianNfb2lkYyIsIm5vbmNlIjoiYTQwNGFjN2NjYWEwNGFmNzkzNmJjYTkyNTJkYTRhODUiLCJpYXQiOjE0OTE3NjUzMjEsInNpZCI6IjI2YTYzNWVmOTQ2ZjRiZGU3ZWUzMzQ2ZjFmMWY1NTZjIiwic3ViIjoiODg0MjExMTMiLCJhdXRoX3RpbWUiOjE0OTE3NjUzMTksImlkcCI6ImxvY2FsIiwiYW1yIjpbInB3ZCJdfQ.STzOWoeVYMtZdRAeRT95cMYEmClixWkmGwVH2Yyiks9BETotbSZiSfgE5kRh72kghN78N3-RgCTUmM2edB3bZx4H5ut3wWsBnZtQ2JLfhTwJAjaLE9Ykt68ovNJySbm8hjZhHzPWKh55jzshivQvTX0GdtlbcDoEA1oNONxHkpDIcr3pRoGi6YveEAFsGOeSQwzT76aId-rAALhFPkyKnVc-uB8IHtGNSyRWLFhwVqAdS3fRNO7iIs5hYRxeFSU7a5ZuUqZ6RRi-bcDhI-djKO5uAwiyhfpbpYcaY_TxXWoCmq8N8uAw9zqFsQUwcXymfOAi2UF3eFZt02hBu-shKA&post_logout_redirect_uri=http%3A%2F%2Flocalhost%3A7017%2Findex.html
注意
您可使用IdentityModel客戶端庫以編程方式建立end_session請求.NET代碼。有關更多信息,請查看IdentityModel 文檔。
此類爲身份資源建模。
Enabled
指示此資源是否已啓用且能夠請求。默認爲true。
Name
身份資源的惟一名稱。這是客戶端將用於受權請求中的scope參數的值。
DisplayName
該值將用於例如贊成屏幕上。
Description
該值將用於例如贊成屏幕上。
Required
指定用戶是否能夠在贊成屏幕上取消選擇範圍(若是贊成屏幕要實現此類功能)。默認爲false。
Emphasize
指定贊成屏幕是否會強調此範圍(若是贊成屏幕要實現此類功能)。將此設置用於敏感或重要範圍。默認爲false。
ShowInDiscoveryDocument
指定此範圍是否顯示在發現文檔中。默認爲true。
UserClaims
應包含在身份令牌中的關聯用戶聲明類型的列表。
此類爲API資源建模。
Enabled
指示此資源是否已啓用且能夠請求。默認爲true。
Name
API的惟一名稱。此值用於內省身份驗證,並將添加到傳出訪問令牌的受衆。
DisplayName
該值能夠在例如贊成屏幕上使用。
Description
該值能夠在例如贊成屏幕上使用。
ApiSecrets
API密鑰用於內省端點。API可使用API名稱和密鑰進行內省驗證。
UserClaims
應包含在訪問令牌中的關聯用戶聲明類型的列表。
Scopes
API必須至少有一個範圍。每一個範圍能夠有不一樣的設置。
在簡單的狀況下,API只有一個範圍。可是在某些狀況下,您可能但願細分API的功能,並讓不一樣的客戶端訪問不一樣的部分。
Name
範圍的惟一名稱。這是客戶端將用於受權/令牌請求中的scope參數的值。
DisplayName
該值能夠在例如贊成屏幕上使用。
Description
該值能夠在例如贊成屏幕上使用。
Required
指定用戶是否能夠在贊成屏幕上取消選擇範圍(若是贊成屏幕要實現此類功能)。默認爲false。
Emphasize
指定贊成屏幕是否會強調此範圍(若是贊成屏幕要實現此類功能)。將此設置用於敏感或重要範圍。默認爲false。
ShowInDiscoveryDocument
指定此範圍是否顯示在發現文檔中。默認爲true。
UserClaims
應包含在訪問令牌中的關聯用戶聲明類型的列表。此處指定的聲明將添加到爲API指定的聲明列表中。
只是關於爲ApiResource
類提供的構造函數的註釋。
要徹底控制數據ApiResource
,請使用不帶參數的默認構造函數。若是要爲每一個API配置多個範圍,可使用此方法。例如:
new ApiResource
{
Name = "api2",
Scopes =
{
new Scope()
{
Name = "api2.full_access",
DisplayName = "Full access to API 2"
},
new Scope
{
Name = "api2.read_only",
DisplayName = "Read only access to API 2"
}
}
}
對於每一個API只須要一個範圍的簡單方案,則提供了幾個接受a的便捷構造函數name
。例如:
new ApiResource("api1", "Some API 1")
使用便捷構造函數等同於:
new ApiResource
{
Name = "api1",
DisplayName = "Some API 1",
Scopes =
{
new Scope()
{
Name = "api1",
DisplayName = "Some API 1"
}
}
}
該Client
級車型的ID鏈接或OAuth 2.0用戶端-例如,本地應用,Web應用程序或基於JS的應用程序。
Enabled
指定是否啓用客戶端。默認爲true。
ClientId
客戶端的惟一ID
ClientSecrets
客戶端機密列表 - 訪問令牌端點的憑據。
RequireClientSecret
指定此客戶端是否須要密鑰才能從令牌端點請求令牌(默認爲true
)
AllowedGrantTypes
指定容許客戶端使用的受權類型。將該GrantTypes
類用於常見組合。
RequirePkce
指定使用基於受權代碼的受權類型的客戶端是否必須發送校驗密鑰
AllowPlainTextPkce
指定使用PKCE的客戶端是否可使用純文本代碼質詢(不推薦 - 默認爲false
)
RedirectUris
指定容許的URI以返回令牌或受權碼
AllowedScopes
默認狀況下,客戶端無權訪問任何資源 - 經過添加相應的範圍名稱來指定容許的資源
AllowOfflineAccess
指定此客戶端是否能夠請求刷新令牌(請求offline_access
範圍)
AllowAccessTokensViaBrowser
指定是否容許此客戶端經過瀏覽器接收訪問令牌。這對於強化容許多種響應類型的流是有用的(例如,經過禁止混合流客戶端,該客戶端應該使用代碼id_token來添加令牌響應類型,從而將令牌泄露給瀏覽器。
Properties
字典可根據須要保存任何自定義客戶端特定值。
PostLogoutRedirectUris
指定在註銷後重定向到的容許URI。有關更多詳細信息,請參閱OIDC Connect會話管理規範。
FrontChannelLogoutUri
指定客戶端的註銷URI,以用於基於HTTP的前端通道註銷。有關詳細信息,請參閱OIDC Front-Channel規範。
FrontChannelLogoutSessionRequired
指定是否應將用戶的會話ID發送到FrontChannelLogoutUri。默認爲true。
BackChannelLogoutUri
指定客戶端的註銷URI,以用於基於HTTP的反向通道註銷。有關詳細信息,請參閱OIDC Back-Channel規範。
BackChannelLogoutSessionRequired
指定是否應在請求中將用戶的會話ID發送到BackChannelLogoutUri。默認爲true。
EnableLocalLogin
指定此客戶端是否能夠僅使用本地賬戶或外部IdP。默認爲true。
IdentityProviderRestrictions
指定能夠與此客戶端一塊兒使用的外部IdP(若是列表爲空,則容許全部IdP)。默認爲空。
IdentityTokenLifetime
標識令牌的生命週期(以秒爲單位)(默認爲300秒/ 5分鐘)
AccessTokenLifetime
訪問令牌的生命週期(以秒爲單位)(默認爲3600秒/ 1小時)
AuthorizationCodeLifetime
受權代碼的生命週期(以秒爲單位)(默認爲300秒/ 5分鐘)
AbsoluteRefreshTokenLifetime
刷新令牌的最長生命週期,以秒爲單位。默認爲2592000秒/ 30天
SlidingRefreshTokenLifetime
刷新令牌的生命週期以秒爲單位。默認爲1296000秒/ 15天
RefreshTokenUsage
ReUse
刷新令牌時刷新令牌句柄將保持不變OneTime
刷新令牌時將更新刷新令牌句柄。這是默認值。
RefreshTokenExpiration
Absolute
刷新令牌將在固定時間點到期(由AbsoluteRefreshTokenLifetime指定)Sliding
刷新令牌時,將刷新刷新令牌的生命週期(按SlidingRefreshTokenLifetime中指定的數量)。生命週期不會超過AbsoluteRefreshTokenLifetime。
UpdateAccessTokenClaimsOnRefresh
獲取或設置一個值,該值指示是否應在刷新令牌請求上更新訪問令牌(及其聲明)。
AccessTokenType
指定訪問令牌是引用令牌仍是自包含JWT令牌(默認爲Jwt)。
IncludeJwtId
指定JWT訪問令牌是否應具備嵌入的惟一ID(經過jti聲明)。
AllowedCorsOrigins
若是指定,將由默認CORS策略服務實現(內存和EF)用於爲JavaScript客戶端構建CORS策略。
Claims
容許客戶端的設置聲明(將包含在訪問令牌中)。
AlwaysSendClientClaims
若是設置,將爲每一個流發送客戶端聲明。若是不是,僅用於客戶端憑證流(默認爲false)
AlwaysIncludeUserClaimsInIdToken
在請求id令牌和訪問令牌時,若是用戶聲明始終將其添加到id令牌而不是請求客戶端使用userinfo端點。默認值爲false。
ClientClaimsPrefix
若是設置,前綴客戶端聲明類型將之前綴爲。默認爲client_。目的是確保它們不會意外地與用戶聲明衝突。
PairWiseSubjectSalt
對於此客戶端的用戶,在成對的subjectId生成中使用的salt值。
RequireConsent
指定是否須要贊成屏幕。默認爲true。
AllowRememberConsent
指定用戶是否能夠選擇存儲贊成決策。默認爲true。
ConsentLifetime
用戶贊成的生命週期,以秒爲單位。默認爲null(無到期)。
ClientName
客戶端顯示名稱(用於記錄和贊成屏幕)
ClientUri
有關客戶端的更多信息的URI(在贊成屏幕上使用)
LogoUri
URI到客戶端徽標(在贊成屏幕上使用)
該GrantValidationResult
級車型補助確認爲擴展贈款和資源全部者密碼受權的結果。
最多見的用法是使用身份(成功案例)新建它:
context.Result = new GrantValidationResult(
subject: "818727",
authenticationMethod: "custom",
claims: optionalClaims);
...或使用錯誤和描述(失敗案例):
context.Result = new GrantValidationResult(
TokenRequestErrors.InvalidGrant,
"invalid custom credential");
在這兩種狀況下,您均可以傳遞將包含在令牌響應中的其餘自定義值。
IdentityServer一般在建立令牌或處理對userinfo或內省端點的請求時須要有關用戶的身份信息。默認狀況下,IdentityServer僅在身份驗證cookie中具備聲明,以便爲此身份數據進行繪製。
將用戶所需的全部可能聲明放入cookie中是不切實際的,所以IdentityServer定義了一個擴展點,容許根據用戶須要動態加載聲明。這個可擴展點是IProfileService
開發人員一般能夠實現此接口來訪問包含用戶身份數據的自定義數據庫或API。
GetProfileDataAsync
預期爲用戶加載聲明的API。它傳遞了一個實例ProfileDataRequestContext
。
IsActiveAsync
預期用於指示當前是否容許用戶獲取令牌的API。它傳遞了一個實例IsActiveContext
。
模擬用戶聲明的請求,而且是返回這些聲明的工具。它包含如下屬性:
Subject
該ClaimsPrincipal
模型的用戶。
Client
的Client
用於正被請求的權利要求。
RequestedClaimTypes
請求的索賠類型集合。
Caller
正在請求聲明的上下文的標識符(例如,身份令牌,訪問令牌或用戶信息端點)。常量IdentityServerConstants.ProfileDataCallers
包含不一樣的常量值。
IssuedClaims
Claim
將返回的s 列表。預計這將由自定義IProfileService
實現填充。
AddRequestedClaims
擴展方法對ProfileDataRequestContext
填充IssuedClaims
,但首先過濾基於的聲明RequestedClaimTypes
。
客戶端請求的範圍控制用戶聲明在令牌中返回給客戶端的內容。該GetProfileDataAsync
方法負責根據上的RequestedClaimTypes
集合動態獲取這些聲明ProfileDataRequestContext
。
該RequestedClaimTypes
集合是基於該定義的用戶索賠人口資源的範圍進行建模。若是請求的範圍是身份資源,則將RequestedClaimTypes
根據在中定義的用戶聲明類型填充聲明中的聲明IdentityResource
。若是請求的範圍是API資源,則將RequestedClaimTypes
根據ApiResource
和/或中定義的用戶聲明類型填充聲明中的聲明Scope
。
對要肯定的請求建模是當前容許用戶獲取令牌。它包含如下屬性:
Subject
該ClaimsPrincipal
模型的用戶。
Client
的Client
用於正被請求的權利要求。
Caller
正在請求聲明的上下文的標識符(例如,身份令牌,訪問令牌或用戶信息端點)。常量IdentityServerConstants.ProfileDataCallers
包含不一樣的常量值。
IsActive
指示是否容許用戶獲取令牌的標誌。預計這將由自定義IProfileService
實現分配。
該IIdentityServerInteractionService
接口旨在提供用戶界面用於與IdentityServer通訊的服務,主要涉及用戶交互。它能夠從依賴注入系統得到,一般做爲構造函數參數注入到IdentityServer的用戶界面的MVC控制器中。
GetAuthorizationContextAsync
返回AuthorizationRequest
基於returnUrl
傳遞給登陸或贊成頁面。
IsValidReturnUrl
指示returnUrl
登陸或贊成後是否爲重定向的有效URL。
GetErrorContextAsync
返回ErrorMessage
基於errorId
傳遞給錯誤頁面。
GetLogoutContextAsync
返回LogoutRequest
基於logoutId
傳遞給註銷頁面。
CreateLogoutContextAsync
logoutId
若是目前沒有一個用於建立。這將建立一個cookie,捕獲註銷所需的全部當前狀態,並logoutId
標識該cookie。這一般在沒有當前時使用,logoutId
而且註銷頁面必須捕獲當前用戶在重定向到外部身份提供程序以進行註銷以前註銷所需的狀態。新建立的logoutId
須要在註銷時往返外部身份提供商,而後在註銷回調頁面上使用,就像在普通註銷頁面上同樣。
GrantConsentAsync
接受a ConsentResponse
以通知IdentityServer用戶贊成某個特定用戶AuthorizationRequest
。
GetAllUserConsentsAsync
返回Consent
用戶的集合。
RevokeUserConsentAsync
撤消用戶對用戶的全部贊成和受權。
RevokeTokensForCurrentSessionAsync
撤消用戶在當前會話期間簽署的客戶的全部贊成和受權。
ClientId
發起請求的客戶端標識符。
RedirectUri
成功受權後將用戶重定向到的URI。
DisplayMode
顯示模式從受權請求傳遞。
UiLocales
從受權請求傳遞的UI語言環境。
IdP
外部身份提供者請求。這用於繞過家庭領域發現(HRD)。這是經過「idp:」前綴提供給acr_values
受權請求的參數。
Tenant
租客要求。這是經過「tenant:」前綴提供給acr_values
受權請求的參數。
LoginHint
用戶將用於登陸的預期用戶名。這是經過login_hint
受權請求上的參數從客戶端請求的。
PromptMode
從受權請求請求的提示模式。
AcrValues
從受權請求傳遞的acr值。
ScopesRequested
受權請求中請求的範圍。
Parameters
整個參數集合傳遞給受權請求。
DisplayMode
顯示模式從受權請求傳遞。
UiLocales
從受權請求傳遞的UI語言環境。
Error
錯誤代碼。
RequestId
每請求標識符。這可用於向最終用戶顯示,並可用於診斷。
ClientId
發起請求的客戶端標識符。
PostLogoutRedirectUri
用戶在註銷後將其重定向到的URL。
SessionId
用戶當前的會話ID。
SignOutIFrameUrl
要在<iframe>
註銷頁面上呈現以啓用單點註銷的URL 。
Parameters
整個參數集合傳遞給結束會話端點。
ShowSignoutPrompt
指示是否應根據傳遞到結束會話端點的參數提示用戶註銷。
ScopesConsented
用戶贊成的範圍集合。
RememberConsent
指示是否持久保留用戶贊成的標誌。
SubjectId
授予贊成的主題ID。
ClientId
贊成的客戶端標識符。
Scopes
範圍的集合贊成。
CreationTime
得到贊成的日期和時間。
Expiration
贊成過時的日期和時間。
IssuerUri
設置將在發現文檔和已頒發的JWT令牌中顯示的頒發者名稱。建議不要設置此屬性,該屬性從客戶端使用的主機名中推斷頒發者名稱。
PublicOrigin
此服務器實例的來源,例如https://myorigin.com。若是未設置,則從請求推斷出原始名稱。
容許啓用/禁用各個端點,例如令牌,受權,用戶信息等。
默認狀況下,全部端點都已啓用,但您能夠經過禁用不須要的端點來鎖定服務器。
容許啓用/禁用發現文檔的各個部分,例如端點,範圍,聲明,受權類型等。
該CustomEntries
字典容許向發現文檔添加自定義元素。
CookieLifetime
身份驗證cookie生存期(僅在使用IdentityServer提供的cookie處理程序時有效)。
CookieSlidingExpiration
指定cookie是否應該滑動(僅在使用IdentityServer提供的cookie處理程序時有效)。
RequireAuthenticatedUserForSignOutMessage
指示是否必須對用戶進行身份驗證以接受結束會話端點的參數。默認爲false。
CheckSessionCookieName
用於檢查會話端點的cookie的名稱。
RequireCspFrameSrcForSignout
若是設置,將要求frame-src CSP標頭在結束會話回調端點上發出,該端點向客戶端呈現iframe以進行前端通道註銷通知。默認爲true。
容許配置是否應將哪些事件提交到已註冊的事件接收器。有關活動的更多信息,請參見此處。
容許設置各類協議參數的長度限制,如客戶端ID,範圍,重定向URI等。
LoginUrl
,LogoutUrl
,ConsentUrl
,ErrorUrl
設置登陸,註銷,贊成和錯誤頁面的URL。
LoginReturnUrlParameter
設置傳遞給登陸頁面的返回URL參數的名稱。默認爲returnUrl。
LogoutIdParameter
設置傳遞給註銷頁面的註銷消息id參數的名稱。默認爲logoutId。
ConsentReturnUrlParameter
設置傳遞給贊成頁面的返回URL參數的名稱。默認爲returnUrl。
ErrorIdParameter
設置傳遞給錯誤頁面的錯誤消息id參數的名稱。默認爲errorId。
CustomRedirectReturnUrlParameter
設置從受權端點傳遞給自定義重定向的返回URL參數的名稱。默認爲returnUrl。
CookieMessageThreshold
IdentityServer和某些UI頁面之間的某些交互須要cookie來傳遞狀態和上下文(上面的任何具備可配置「message id」參數的頁面)。因爲瀏覽器對cookie的數量及其大小有限制,所以該設置用於防止建立過多的cookie。該值設置將建立的任何類型的消息cookie的最大數量。一旦達到限制,將清除最先的消息cookie。這有效地表示用戶在使用IdentityServer時能夠打開多少個選項卡。
這些設置僅在啓動時在服務配置中啓用了相應的緩存時才適用。
ClientStoreExpiration
從客戶端存儲加載的客戶端配置的緩存持續時間。
ResourceStoreExpiration
緩存從資源存儲加載的標識和API資源配置的持續時間。
IdentityServer支持某些端點的CORS。底層CORS實現由ASP.NET Core提供,所以它在依賴注入系統中自動註冊。
CorsPolicyName
將爲IdentityServer中的CORS請求評估的CORS策略的名稱(默認爲"IdentityServer4"
)。處理此問題的策略提供程序是根據ICorsPolicyService
依賴注入系統中註冊的方式實現的。若是您但願自定義容許鏈接的CORS源集,那麼建議您提供自定義實現ICorsPolicyService
。
CorsPaths
IdentityServer中支持CORS的端點。默認爲發現,用戶信息,令牌和吊銷端點。
PreflightCacheDuration
Nullable <TimeSpan>指示在預檢Access-Control-Max-Age響應頭中使用的值。默認爲null,表示未在響應上設置緩存標頭。
在適當的狀況下,IdentityServer會爲某些響應發出CSP標頭。
Level
要使用的CSP級別。默認狀況下使用CSP級別2,但若是必須支持舊瀏覽器,則將其更改CspLevel.One
爲容納它們。
AddDeprecatedHeader
指示是否X-Content-Security-Policy
還應發出較舊的CSP標頭(除了基於標準的標頭值)。默認爲true。
爲IdentityServer中的配置和操做數據擴展點提供了基於EntityFramework的實現。EntityFramework的使用容許任何EF支持的數據庫與此庫一塊兒使用。
此庫提供的功能分爲兩個主要區域:配置存儲和操做存儲支持。根據託管應用程序的須要,這兩個不一樣的區域能夠獨立使用或一塊兒使用。
若是但願從EF支持的數據庫加載客戶端,標識資源,API資源或CORS數據(而不是使用內存配置),則可使用配置存儲。此支持提供了IClientStore
和IResourceStore
,以及ICorsPolicyService
可擴展性點的實現。這些實現使用一個DbContext
被調用的類ConfigurationDbContext
來爲數據庫中的表建模。
要使用配置存儲支持,請AddConfigurationStore
在調用後使用擴展方法AddIdentityServer
:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
const string connectionString = @"Data Source=(LocalDb)\MSSQLLocalDB;database=IdentityServer4.EntityFramework-2.0.0;trusted_connection=yes;";
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddIdentityServer()
// this adds the config data from DB (clients, resources, CORS)
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
});
}
要配置配置存儲,請使用ConfigurationStoreOptions
傳遞給配置回調的options對象。
此選項類包含用於控制配置存儲的屬性ConfigurationDbContext
。
ConfigureDbContext
Action<DbContextOptionsBuilder>
用做回調的類型委託來配置底層證券ConfigurationDbContext
。ConfigurationDbContext
若是直接使用EF,代理能夠以相同的方式配置AddDbContext
,這容許使用任何EF支持的數據庫。
DefaultSchema
容許爲中的全部表設置默認數據庫模式名稱ConfigurationDbContext
。
若是但願從EF支持的數據庫(而不是默認的內存數據庫)加載受權授予,贊成和令牌(刷新和引用),則可使用操做存儲。此支持提供了IPersistedGrantStore
可擴展性點的實現。該實現使用一個DbContext
被調用的類PersistedGrantDbContext
來爲數據庫中的表建模。
要使用操做商店支持,請AddOperationalStore
在調用後使用擴展方法AddIdentityServer
:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
const string connectionString = @"Data Source=(LocalDb)\MSSQLLocalDB;database=IdentityServer4.EntityFramework-2.0.0;trusted_connection=yes;";
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddIdentityServer()
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
// this enables automatic token cleanup. this is optional.
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 30; // interval in seconds
});
}
要配置操做存儲,請使用OperationalStoreOptions
傳遞給配置回調的options對象。
此選項類包含用於控制操做存儲的屬性PersistedGrantDbContext
。
ConfigureDbContext
Action<DbContextOptionsBuilder>
用做回調的類型委託來配置底層證券PersistedGrantDbContext
。PersistedGrantDbContext
若是直接使用EF,代理能夠以相同的方式配置AddDbContext
,這容許使用任何EF支持的數據庫。
DefaultSchema
容許爲中的全部表設置默認數據庫模式名稱PersistedGrantDbContext
。
EnableTokenCleanup
指示是否將從數據庫中自動清除過期條目。默認是false
。
TokenCleanupInterval
令牌清理間隔(以秒爲單位)。默認值爲3600(1小時)。
跨不一樣版本的IdentityServer(以及EF支持)極可能會更改數據庫架構以適應新的和不斷變化的功能。
咱們不爲建立數據庫或將數據從一個版本遷移到另外一個版本提供任何支持。您須要以組織認爲合適的任何方式管理數據庫建立,架構更改和數據遷移。
使用EF遷移是一種可行的方法。若是您確實但願使用遷移,請參閱EF快速入門以獲取有關如何入門的示例,或參閱有關EF遷移的Microsoft 文檔。
咱們還爲當前版本的數據庫模式發佈了示例SQL腳本。
提供了基於ASP.NET身份的實現,用於管理IdentityServer用戶的身份數據庫。此實現實現IdentityServer中的擴展點,以便爲用戶加載身份數據以將聲明發送到令牌。
要使用此庫,請正常配置ASP.NET標識。而後AddAspNetIdentity
在調用後使用擴展方法AddIdentityServer
:
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddIdentityServer()
.AddAspNetIdentity<ApplicationUser>();
}
AddAspNetIdentity
須要做爲通用參數來爲您的用戶建模ASP.NET身份的類(以及傳遞給AddIdentity
ASP.NET身份的同一個用戶)。這將配置IdentityServer使用的ASP.NET身份的實現IUserClaimsPrincipalFactory
,IResourceOwnerPasswordValidator
和IProfileService
。它還配置了一些用於IdentityServer的ASP.NET Identity選項(例如要使用的聲明類型和身份驗證cookie設置)。
如下是一些在線,遠程和課堂培訓選項,以瞭解有關ASP.NET核心身份和IdentityServer4的更多信息。
這是咱們爲期三天的旗艦課程(包括普遍的實踐實驗室),咱們做爲會議,現場和遠程的一部分提供。
可在此處找到公共培訓的議程和日期,請 聯繫咱們參加私人研討會。
PluralSight有一些關於身份,ASP.NET Core和IdentityServer的好課程。
新
舊的
[17/01 NDC London] - ASP.NET Core v2上的IdentityServer v2 - 一個更新
[17/01 DotNetRocks] - DotNetRocks上的IdentityServer和PolicyServer
[14/09 Microsoft Learning] - IdentityServer for ASP.NET Core簡介 - Brock Allen
[14/06 NDC Oslo] - 實施Web應用程序和API的受權
[22/02 NDC Mini Copenhagen] - IdentityServer4:ASP.NET核心的新增和改進 - Dominick Baier