歡迎IdentityServer4 IdentityServer4是ASP.NET Core 2的OpenID Connect和OAuth 2.0框架。 它在您的應用程式中啟用以下功能: 認證即服務 適用於所有應用程式(Web,本機,移動設備,服務)的集中登錄邏輯和工作流程。IdentityServ ...
IdentityServer4是ASP.NET Core 2的OpenID Connect和OAuth 2.0框架。
它在您的應用程式中啟用以下功能:
認證即服務
適用於所有應用程式(Web,本機,移動設備,服務)的集中登錄邏輯和工作流程。IdentityServer是OpenID Connect 的官方認證實現。
單點登錄/註銷
在多種應用程式類型上單點登錄(和退出)。
API的訪問控制
為各種類型的客戶端發出API訪問令牌,例如伺服器到伺服器,Web應用程式,SPA和本機/移動應用程式。
聯合網關
支持Azure Active Directory,Google,Facebook等外部身份提供商。這可以保護您的應用程式免受如何連接到這些外部提供商的詳細信息的影響。
專註於定製
最重要的部分 - IdentityServer的許多方面都可以根據您的需求進行定製。由於IdentityServer是一個框架而不是盒裝產品或SaaS,因此您可以編寫代碼以使系統適應您的方案。
成熟的開源
IdentityServer使用允許的Apache 2許可證,允許在其上構建商業產品。它也是.NET Foundation的一部分,它提供治理和法律支持。
免費和商業支持
如果您需要幫助構建或運行您的身份平臺,請告知我們。我們可以通過多種方式為您提供幫助。
大圖
大多數現代應用程式或多或少看起來像這樣:
最常見的互動是:
-
瀏覽器與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訪問
應用程式有兩種與API通信的基本方式 - 使用應用程式標識或委派用戶的標識。有時兩種方法都需要結合起來。
OAuth2是一種協議,允許應用程式從安全令牌服務請求訪問令牌並使用它們與API通信。此委派降低了客戶端應用程式和API的複雜性,因為身份驗證和授權可以集中。
OpenID Connect和OAuth 2.0 - 更好地結合在一起
OpenID Connect和OAuth 2.0非常相似 - 事實上,OpenID Connect是OAuth 2.0之上的擴展。兩個基本的安全問題,即身份驗證和API訪問,被合併為一個協議 - 通常只需要一次往返安全令牌服務。
我們相信,OpenID Connect和OAuth 2.0的結合是在可預見的未來保護現代應用程式的最佳方法。IdentityServer4是這兩種協議的實現,經過高度優化,可以解決當今移動,本機和Web應用程式的典型安全問題。
IdentityServer4如何提供幫助
IdentityServer是一個中間件,可將符合規範的OpenID Connect和OAuth 2.0端點添加到任意ASP.NET Core應用程式中。
通常,您構建(或重用)包含登錄和註銷頁面的應用程式(並且可能同意 - 取決於您的需要),IdentityServer中間件為其添加必要的協議頭,以便客戶端應用程式可以與之通信使用那些標準協議。
托管應用程式可以像您想要的那樣複雜,但我們通常建議通過僅包含與身份驗證相關的UI來使攻擊面儘可能小。
術語
規範,文檔和對象模型使用您應該註意的某些術語。
IdentityServer
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實現以下規範:
ID連接
-
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用戶
-
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包組成。
IdentityServer4
包含核心IdentityServer對象模型,服務和中間件。僅包含對記憶體配置和用戶存儲的支持 - 但您可以通過配置插入對其他存儲的支持。這是其他回購和包裝的內容。
快速入門
包含一個簡單的入門UI,包括登錄,註銷和同意頁面。
訪問令牌驗證處理程式
用於驗證API中令牌的ASP.NET Core身份驗證處理程式。處理程式允許在同一API中支持JWT和引用令牌。
ASP.NET核心標識
IdentityServer的ASP.NET核心身份集成包。該軟體包提供了一個簡單的配置API,可以為IdentityServer用戶使用ASP.NET身份管理庫。
EntityFramework核心
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
要將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再次<