本文于 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
以进行测试。