Index()
{
string accessToken = await HttpContext.GetTokenAsync("access_token");
string refreshToken = await HttpContext.GetTokenAsync("refresh_token");
return Content($"Current user: {User.Identity.Name ?? "anonymous"}
" +
$"Access token: {accessToken}
" +
$"Refresh token: {refreshToken}
"
, "text/html");
}
}
現在、ブラウザでこのコントローラに移動すると、SIサーバへのリダイレクトが試みられ、認証に成功すると、このページが表示されます。
.. code-block::
Current user: sitecore\Admin
Access token: eyJhbG......L8A
Refresh token: 4cdf3b4d873a65135553afdf420a47dbc898ba0c1c0ece2407bbbf2bde02a68b
6. このアクションをホームコントローラに追加して、ベアラートークンでAPIを呼び出すようにします。
.. code-block::
[Route("/callapi")]
public async Task CallApi()
{
string accessToken = await HttpContext.GetTokenAsync("access_token");
var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:55600/identity");
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
HttpResponseMessage response = await HttpClient.SendAsync(request);
if (response.StatusCode != HttpStatusCode.OK)
{
return Content(response.ToString());
}
return Content($"{await response.Content.ReadAsStringAsync()}");
}
7. access_token 引数を渡すことで、GetTokenAsync メソッドを使用して、HttpContext からベアラ (アクセス) トークンを取得します。このようにして、アクセストークンをリクエスト・ヘッダに追加します。
.. code-block::
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
http://localhost:54567/callapi urlに移動します。答えは以下のようになるはずです。
.. code-block::
[
{
"type": "nbf",
"value": "1543572239"
},
{
"type": "exp",
"value": "1543572359"
},
{
"type": "iss",
"value": "https://localhost:44356"
},
{
"type": "aud",
"value": "https://localhost:44356/resources"
},
{
"type": "aud",
"value": "sitecore.profile.api"
},
{
"type": "client_id",
"value": "MvcClient"
},
{
"type": "name",
"value": "sitecore\\Admin"
},
........
呼び出し元の URL (http://localhost:55600/identity) を変更して、別の API、例えば Sitecore アイテムサービスなどを呼び出すことができます。
.. code-block:: json
{
"ItemID": "110d559f-dea5-42ea-9c1c-8a5df7e70ef9",
"ItemName": "Home",
"ItemPath": "/sitecore/content/Home",
"ParentID": "0de95ae4-41ab-4d01-9eb0-67441b7c2450",
"TemplateID": "76036f5e-cbce-46d1-af0a-4143f9b557aa",
"TemplateName": "Sample Item",
"CloneSource": null,
"ItemLanguage": "en",
"ItemVersion": "1",
"DisplayName": "Home",
"HasChildren": "False",
"ItemIcon": "/temp/iconcache/network/16x16/home.png",
"ItemMedialUrl": "/-/icon/Network/48x48/home.png.aspx",
"ItemUrl": "~/link.aspx?_id=110D559FDEA542EA9C1C8A5DF7E70EF9&_z=z",
"Text": "<p style.......e</a></p>\r",
"Title": "Sitecore Experience Platform"
}
しばらくすると(SIサーバ上のクライアント設定でAccessTokenLifetimeInSecondsパラメータとして指定されている)、以下のような結果が得られます。
.. code-block::
StatusCode: 401, ReasonPhrase:
'Unauthorized', Version: 1.1, Content:
System.Net.Http.HttpConnection+HttpConnectionResponseContent, Headers:
{
Server:
Kestrel
WWW-Authenticate: Bearer error="invalid_token",
error_description="The token is expired"
X-SourceFiles:
=?UTF-8?B?Qzpcclxfd1xpc1xzYW1wbGVzXEFwaVxpZGVudGl0eQ==?=
X-Powered-By:
ASP.NET
Date: Fri, 30
Nov 2018 07:42:20 GMT
Content-Length: 0
}
つまり、アクセストークンの有効期限が切れているので、新しいアクセストークンを取得する必要があります。次のセクションでは、その方法を説明します。
**************************************************
リフレッシュトークンとアクセストークンの交換
**************************************************
SI サーバーには、プログラムでトークンを要求するために使用するトークンエンドポイントがあります。このサーバは OpenID Connect および OAuth 2.0 トークン要求パラメータのサブセットをサポートしています。OpenID のドキュメントに完全なリストがあります。
トークンを要求するには
1. ホームコントローラに次のアクションを追加します。
.. code-block::
[Route("/exchange")]
public async Task Exchange()
{
var disco = await DiscoveryClient.GetAsync("https://localhost:44356");
if (disco.IsError) throw new Exception(disco.Error);
var tokenClient = new TokenClient(disco.TokenEndpoint, "MvcClient", "secret");
var rt = await HttpContext.GetTokenAsync("refresh_token");
var tokenResult = await tokenClient.RequestRefreshTokenAsync(rt);
if (!tokenResult.IsError)
{
var expiresAt = (DateTime.UtcNow + TimeSpan.FromSeconds(tokenResult.ExpiresIn)).ToString("o", CultureInfo.InvariantCulture);
var authService = HttpContext.RequestServices.GetRequiredService();
AuthenticateResult authenticateResult = await authService.AuthenticateAsync(HttpContext, null);
AuthenticationProperties properties = authenticateResult.Properties;
properties.UpdateTokenValue(OpenIdConnectParameterNames.RefreshToken, tokenResult.RefreshToken);
properties.UpdateTokenValue(OpenIdConnectParameterNames.AccessToken, tokenResult.AccessToken);
properties.UpdateTokenValue(OpenIdConnectParameterNames.ExpiresIn, expiresAt);
await authService.SignInAsync(HttpContext, null, authenticateResult.Principal, authenticateResult.Properties);
return Redirect("/");
}
return BadRequest();
}
TokenClient クラスのインスタンスを使用して、SI サーバに新しいトークンを要求します。この要求の前に有効なリフレッシュ・トークンが必要です。成功したリクエスト (RequestRefreshTokenAsync) の後、このリフレッシュ・トークンは無効になり、クッキー内のリフレッシュ・トークンとアクセス・トークンを新しいもので更新する必要があります。
2. AuthenticateAsyncメソッドを呼び出して認証プロパティを取得します。UpdateTokenValueメソッドはトークンを更新し、プロパティ内の有効期限のタイムスタンプも更新し、最後にSignInAsyncメソッドは認証クッキーを保存します。
これでGetTokenAsyncメソッドは更新されたアクセスまたは更新されたトークンを返します。
.. tip:: 英語版 https://doc.sitecore.com/developers/93/sitecore-experience-manager/en/use-bearer-tokens-in-client-applications.html