---
title: "クライアントアプリケーションでベアラートークンを使用する"
slug: "use-bearer-tokens-in-client-applications"
abstract: "Sitecore Identityは、Sitecoreログインのメカニズムを提供します。"
---
# クライアントアプリケーションでベアラートークンを使用する

このトピックでは、ベアラートークン認証とSitecore Identityサーバーを使ってMVCクライアントからAPIに安全にアクセスする方法について説明します。

ベアラートークン認証には3つの要素が含まれます。

-   Sitecore Identity(SI)サーバーです。SIサーバーはデフォルトでJWT(JSON Web Token)形式でアクセストークンを発行します。現在、関連するすべてのプラットフォームはJWTトークンの検証をサポートしています。 *アクセス* トークンと *ベアラー* トークンは同じものと考えることができます。
-   APIアプリケーションです。
-   MVCクライアントアプリケーションです。アプリケーションはSIサーバーからアクセストークンを要求し、それを使ってAPIへのアクセスを得ます。

本トピックで説明する手順は、以下の仮定に基づく例を使用しています。

-   SIサーバーはhttps://localhost:44356/上で動作します。例を使う場合は実際のURLに変更してください。
    
-   MVCクライアントはIDとしてMvcClientされており、SIサーバー上で次のように設定されています。
    
    <?xml version="1.0" encoding="utf-8"?>
    <Settings>
     <Sitecore>
     <IdentityServer>
     <Clients>
     <SampleMvcClient>
     <ClientId>MvcClient</ClientId>
     <ClientName>Sample MVC client</ClientName>
     <AccessTokenType>0</AccessTokenType>
     <AllowOfflineAccess>true</AllowOfflineAccess>
     <AlwaysIncludeUserClaimsInIdToken>true</AlwaysIncludeUserClaimsInIdToken>
     <AccessTokenLifetimeInSeconds>120</AccessTokenLifetimeInSeconds>
     <IdentityTokenLifetimeInSeconds>120</IdentityTokenLifetimeInSeconds>
     <AllowAccessTokensViaBrowser>true</AllowAccessTokensViaBrowser>
     <RequireConsent>false</RequireConsent>
     <RequireClientSecret>false</RequireClientSecret>
     <AllowedGrantTypes>
     <AllowedGrantType1>client\_credentials</AllowedGrantType1>
     <AllowedGrantType2>hybrid</AllowedGrantType2>
     </AllowedGrantTypes>
     <RedirectUris>
     <RedirectUri1>{AllowedCorsOrigin}/signin-oidc</RedirectUri1>
     </RedirectUris>
     <PostLogoutRedirectUris>
     <PostLogoutRedirectUri1>{AllowedCorsOrigin}/signout-callback-oidc</PostLogoutRedirectUri1>
     </PostLogoutRedirectUris>
     <AllowedCorsOrigins>
     <AllowedCorsOriginsGroup1>http://localhost:54567</AllowedCorsOriginsGroup1>
     </AllowedCorsOrigins>
     <AllowedScopes>
     <AllowedScope1>openid</AllowedScope1>
     <AllowedScope2>sitecore.profile</AllowedScope2>
     <AllowedScope3>sitecore.profile.api</AllowedScope3>
     </AllowedScopes>
     <UpdateAccessTokenClaimsOnRefresh>true</UpdateAccessTokenClaimsOnRefresh>
     </SampleMvcClient>
     </Clients>
     </IdentityServer>
     </Sitecore>
    </Settings>
    

このトピックでは、以下の方法を説明します:

-   [APIの保護](https://doc.sitecore.com/xp/ja/developers/103/sitecore-experience-manager/use-bearer-tokens-in-client-applications.html#UUID-ea238104-64cd-6da6-8e2f-f50fd0eab528_section-5c35c4dc0c8ec-idm46016444322112 "Protect the API")
-   [MVCクライアントの設定](https://doc.sitecore.com/xp/ja/developers/103/sitecore-experience-manager/use-bearer-tokens-in-client-applications.html#UUID-ea238104-64cd-6da6-8e2f-f50fd0eab528_section-5c35e68c4329a-idm46779796924496 "Configure the MVC client")
-   [交換、更新およびアクセストークン](https://doc.sitecore.com/xp/ja/developers/103/sitecore-experience-manager/use-bearer-tokens-in-client-applications.html#UUID-ea238104-64cd-6da6-8e2f-f50fd0eab528_section-5c35f80a7c409-idm46533139049616 "Exchange refresh and access tokens")

## APIの保護

この節では、SIサーバーとベアラートークン認証を用いてAPIを保護する基本的なシナリオを概説します。ASP.NETコアベースのAPIを保護するには、DIでJWTベアラー認証ハンドラを設定し、認証ミドルウェアをパイプラインに追加するだけです。

APIを保護するために:

1.  *ASP.NET Core Web API*テンプレートを使ってVisual Studio新しいプロジェクトを作成し、ローンチプロファイルでアプリケーションURLを設定してください。ここで使っている例は、APIをhttp://localhost:55600/として設定することを前提としています。このURLを、自分のソリューションで実際に使っているURLに置き換えてください。
    
2.  プロジェクトへのパッケージ参照を追加:
    
    <Project Sdk="Microsoft.NET.Sdk.Web">
     <PropertyGroup>
     <TargetFramework>netcoreapp2.1</TargetFramework>
     </PropertyGroup>
     <ItemGroup>
     <PackageReference Include="Microsoft.AspNetCore.App" />
     </ItemGroup>
    </Project>
    
3.  Startupクラスの設定:
    
    public class Startup
    {
     public void ConfigureServices(IServiceCollection services)
     {
     services.AddMvcCore()
     .AddAuthorization()
     .AddJsonFormatters();
    
     services.AddAuthentication("Bearer")
     .AddJwtBearer("Bearer", options =>
     {
     options.Authority = "https://localhost:44356";
     options.RequireHttpsMetadata = false;
    
     options.Audience = "sitecore.profile.api";
     });
     }
    
     public void Configure(IApplicationBuilder app, IHostingEnvironment env)
     {
     app.UseAuthentication();
     app.UseMvc();
     }
    }
    
    AddAuthenticationメソッドは認証サービスを追加し、Bearerをデフォルト方式として設定します。AddJwtBearerメソッドはSIサーバーのアクセストークン検証ハンドラを追加し、認証サービスがそれを利用できるようにします。UseAuthenticationメソッドは認証ミドルウェアをパイプラインに追加し、ホストへのすべての呼び出しで自動的に認証が実行されます。
    
4.  APIプロジェクトに新しいコントローラーを追加する:
    
    Route("controller")
    Authorize
    public class IdentityController : ControllerBase
    {
     HttpGet
     public IActionResult Get()
     {
     return new JsonResult(from c in User.Claims
     select new
     {
     c.Type,
     c.Value
     });
     }
    }
    

コントローラー(http://localhost:55600/identity)にアクセスすると、返401ステータスコードが表示されます。これはAPIが認証情報を必要とし、SIサーバーによって保護されていることを示しています。

## MVCクライアントの設定

MVCクライアントに保護されたAPIを使用するように設定するには:

1.  起動プロファイルでアプリケーションURLを設定してください。以下の例は、http://localhost:54567/ をURLとしてMVCクライアントを設定していると仮定しています。このURLを、SIサーバークライアント設定のAllowedCorsOriginsGroup1ノードで実際に使っているURLに置き換えてください。
    
2.  プロジェクトへのパッケージ参照を追加:
    
    <Project Sdk="Microsoft.NET.Sdk.Web">
     <PropertyGroup>
     <TargetFramework>netcoreapp2.1</TargetFramework>
     </PropertyGroup>
    
     <ItemGroup>
     <PackageReference Include="Microsoft.AspNetCore.All" Version="2.1.3" />
     <PackageReference Include="Microsoft.AspNetCore.Authentication.Abstractions" Version="2.1.1.0" />
     <PackageReference Include="IdentityModel" Version="3.8.0" />
     </ItemGroup>
    </Project>
    
3.  MVCアプリケーションのStartupクラスのConfigureServicesメソッドで、クッキーとOpenID Connect認証のサポートを追加します。
    
    public class Startup
    {
     public void ConfigureServices(IServiceCollection services)
     {
     services.AddMvc();
    
     services.AddAuthentication(options =>
     {
     options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
     options.DefaultChallengeScheme = "oidc";
     })
     .AddCookie(options =>
     {
     options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
     options.Cookie.Name = "mvcimplicit";
     })
     .AddOpenIdConnect("oidc", options =>
     {
     options.ClientId = "MvcClient";
     options.Authority = "https://localhost:44356";
     options.RequireHttpsMetadata = false;
     options.GetClaimsFromUserInfoEndpoint = true;
     options.ResponseType = "code token";
    
     options.Scope.Clear();
     options.Scope.Add("openid");
     options.Scope.Add("sitecore.profile");
     options.Scope.Add("offline\_access");
     options.Scope.Add("sitecore.profile.api");
    
     options.SaveTokens = true;
    
     options.TokenValidationParameters = new TokenValidationParameters
     {
     NameClaimType = JwtClaimTypes.Name,
     RoleClaimType = JwtClaimTypes.Role,
     };
     });
     }
    
     public void Configure(IApplicationBuilder app, IHostingEnvironment env)
     {
     app.UseDeveloperExceptionPage();
     app.UseStaticFiles();
     app.UseAuthentication();
     app.UseMvcWithDefaultRoute();
     }
    }
    
    AddAuthentication方式は認証サービスを追加します。クッキーはユーザー認証の主要な手段であり、Cookiesが*DefaultScheme*として指定されているためです。DefaultChallengeSchemeがoidcとして指定されているため、ユーザーがログインする際にOpenID Connect方式を使用する必要があります。
    
    AddCookieメソッドはクッキーを処理できるハンドラーを追加します。
    
    AddOpenIdConnectメソッドはOpenID Connectプロトコルを実行するハンドラーを設定します。AuthorityプロパティはSIサーバーが信頼されていることを示します。このクライアントはClientIdプロパティで識別できます。SignInSchemeメソッドは、OpenID Connectプロトコルが完了するとクッキーハンドラーを使ってクッキーを発行します。SaveTokensメソッドは、SIサーバーからのトークンをクッキー内に永続化します(後で必要になります)。ResponseTypeプロパティをcode tokenとして指定してください(これは実質的にハイブリッドフローを使うことを意味します)。
    
4.  ConfigureメソッドでUseAuthenticationメソッドを呼び出して、各リクエストに対して認証サービスが実行されることを確認してください。パイプラインにMVCする前に認証ミドルウェアを追加する必要があります。
    
5.  認証ハンドシェイクを発動するには、HomeコントローラーにAuthorize属性を追加してください:
    
    Authorize
    public class Home : Controller
    {
     private static readonly HttpClient HttpClient = new HttpClient();
    
     public async Task<IActionResult> Index()
     {
     string accessToken = await HttpContext.GetTokenAsync("access\_token");
     string refreshToken = await HttpContext.GetTokenAsync("refresh\_token");
    
     return Content($"Current user: <span id=\\"UserIdentityName\\">{User.Identity.Name ?? "anonymous"}</span><br/>" +
     $"<div>Access token: {accessToken}</div><br/>" +
     $"<div>Refresh token: {refreshToken}</div><br/>"
     , "text/html");
     }
    }
    
    ブラウザでこのコントローラーに移動すると、SIサーバーへのリダイレクトが試みられ、認証が成功すれば以下のページが表示されます。
    
    Current user: sitecore\\Admin
    Access token: eyJhbG......L8A
    Refresh token: 4cdf3b4d873a65135553afdf420a47dbc898ba0c1c0ece2407bbbf2bde02a68b
    
6.  Homeコントローラーにこのアクションを加え、ベアラートークンでAPIを呼び出す:
    
    Route("/callapi")
     public async Task<IActionResult> 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.  GetTokenAsyncメソッドで*access\_token*引数を渡すことで、HttpContextからベアラー(アクセス)トークンを取得します。リクエストヘッダーにアクセストークンを追加する方法は以下の通りです:
    
    request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    
    URL http://localhost:54567/callapiに移動します。答えは次のようになります:
    
    {
    "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)を変更して、例えばSitecoreアイテムサービスを呼び出すために別のAPIを呼び出すことができます。

{
"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&amp;amp;\_z=z",
"Text": "&lt;p style.......e&lt;/a&gt;&lt;/p&gt;\\r",
"Title": "Sitecore Experience Platform"
}

一定時間(SIサーバーのクライアント設定のAccessTokenLifetimeInSecondsパラメータとして指定)すると、次のような結果が得られます:

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のドキュメント [には完全なリストがあります](https://openid.net/specs/openid-connect-core-1_0.html#TokenRequest)。

トークンのリクエストについて:

1.  ホームコントローラーに以下のアクションを追加します:
    
    Route("/exchange")
    public async Task<IActionResult> 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<IAuthenticationService>();
     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メソッドは更新されたアクセストークンやリフレッシュトークンを返します。