本文於 2019/4/3 更新,去掉了舊文的部分講解,主要是關於混合流程和簡化流程的區別,我決定單獨寫一篇博文來介紹。所以本文現在已經為純翻譯。
在之前的快速入門中,我們探討了API訪問和用戶身份認證。現在我們把這兩個部分結合在一起。
OpenID Connect和OAuth 2.0組合的優點在於,您可以使用單一協議和單一交換使用令牌服務來使用這兩種協議。
在之前的快速入門中,我們使用了OpenID Connect 簡化流程。在簡化流程中,所有令牌(身份令牌、訪問令牌)都通過瀏覽器傳輸,這對於身份令牌(IdentityToken)來說是沒有問題的,但是如果是訪問令牌直接通過瀏覽器傳輸,就增加了一定的安全問題。
訪問令牌(AccessToken)比身份令牌(IdentityToken)更敏感,在非必須的情況下,我們不希望將它們暴露給外界。OpenID Connect 包含一個名為“Hybrid(混合)”的流程,它為我們提供了兩全其美的優勢,身份令牌通過瀏覽器傳輸,因此客戶端可以在進行任何更多工作之前對其進行驗證。如果驗證成功,客戶端會通過令牌服務的以獲取訪問令牌。
修改客戶端配置
沒有太多的修改。首先,我們希望允許客戶端使用混合流程,此外我們還希望客戶端允許執行不在用戶上下文中的服務器到服務器API調用(這與我們的客戶端授權模式的快速入門非常相似)。這是使用AllowedGrantTypes
屬性表示的。
接下來我們需要添加一個客戶端密鑰。這將用於獲取訪問令牌。
最后還需要設置 AllowOfflineAccess
,它允許我們通過刷新令牌的方式來實現長期的API訪問。
new Client
{
ClientId = "mvc",
ClientName = "MVC Client",
AllowedGrantTypes = GrantTypes.Hybrid,
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客戶端
MVC客戶端的修改也很少 - ASP.NET Core OpenID Connect 處理程序內置了對混合流程的支持,因此我們只需要更改一些配置值。
配置 ClientSecret
匹配IdentityServer中設置的 Client Secret,Scope 添加 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");
options.ClaimActions.MapJsonKey("website", "website");
});
當您運行MVC客戶端時,除了現在同意授權頁面要求您提供額外的 offline_access和
api1 Scope 之外,沒有太大的區別。
使用訪問令牌
OpenID Connect 處理程序會自動為您保存令牌(在我們的案例中為身份令牌,訪問令牌和刷新令牌)。這就是SaveTokens
設置的作用。
從技術上講,令牌存儲在cookie中。訪問它們的最簡單方法是使用Microsoft.AspNetCore.Authentication
命名空間中的擴展方法。
例如:
var accessToken = await HttpContext.GetTokenAsync("access_token")
var refreshToken = await HttpContext.GetTokenAsync("refresh_token");
要使用訪問令牌訪問API,您需要做的就是先獲取訪問令牌,然后在HttpClient上設置它:
public async Task<IActionResult> CallApi()
{
var accessToken = await HttpContext.GetTokenAsync("access_token");
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var content = await client.GetStringAsync("http://localhost:5001/identity");
ViewBag.Json = JArray.Parse(content).ToString();
return View("json");
}
創建一個名為json.cshtml
json 的視圖:
<pre>@ViewBag.Json</pre>
啟動MVC客戶端並在身份驗證后調用訪問/home/CallApi
以進行測試。