本篇基於前文介紹的API訪問的控制和用戶身份的認證,本篇將在ASP.NET Core應用中把這兩者結合起來。
OpenID Connect和OAuth 2.0組合的優點在於,我們可以通過單一協議和與令牌服務的一次交換來實現。
到目前爲止,我們僅在令牌請求期間請求標識(身份)資源。當我們在獲取令牌後,我們可能需要開始訪問一些 API 資源,此時,我們可以讓IdentityServer 將返回兩個令牌:包含有關身份驗證和會話的信息的標識令牌
,以及代表登錄的用戶訪問 API的訪問令牌
。
認證授權服務中客戶端配置的修改
我們基於前文的認證授權中心服務,修改其客戶端配置:
添加了一個AllowedScopes
:CodeSnippets.WebApi
(這個是待會我們MVC客戶端要訪問的API),以及啓用AllowOfflineAccess
一直吃刷新令牌。
public static IEnumerable<Client> Clients => new List<Client>
{
new Client
{
ClientId="mvc",
ClientSecrets={new Secret("secret".Sha256())},
AllowedGrantTypes=GrantTypes.Code,
RequireConsent=false,
RequirePkce=true,
RedirectUris={ "http://localhost:5002/signin-oidc"},
PostLogoutRedirectUris={ "http://localhost:/5002/signout-callback-oidc"},
AllowedScopes=new List<string>{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
"CodeSnippets.WebApi" // 啓用對刷新令牌的支持
},
AllowOfflineAccess=true
}
};
MVC網站客戶端的修改
添加了兩個scope
:CodeSnippets.WebApi
和offline_access
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
// 添加可以處理cookie的處理程序
.AddCookie("Cookies")
// 用於配置執行OpenID Connect協議的處理程序
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "http://localhost:5000"; // 指示了受信任令牌服務地址
options.RequireHttpsMetadata = false;
options.ClientId = "mvc";
options.ClientSecret = "secret";
options.ResponseType = "code";
options.SaveTokens = true; // 用於將來自IdentityServer的令牌保留在cookie中
options.Scope.Add("CodeSnippets.WebApi");
options.Scope.Add("offline_access");
});
}
使用訪問令牌
訪問API服務
我們只要先獲訪問令牌,然後把他設置到HttpClient上即可(其中位於GetTokenAsync()
方法Microsoft.AspNetCore.Authentication
命名空間下):
public async Task<IActionResult> CallApi()
{
var accessToken = await HttpContext.GetTokenAsync("access_token");
// var refreshToken =await HttpContext.GetTokenAsync(“ refresh_token”);
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
var content = await client.GetStringAsync("http://localhost:5001/identity");
ViewBag.Json = JArray.Parse(content).ToString();
return View();
}
訪問結果如下: