SharePoint アドインの認証コード OAUTH フロー

注:

この記事では、読者が「低信頼承認を使用する SharePoint アドインを作成する」および OAuth の基礎となっている概念や原理を理解していることを前提としています。 OAuth の詳細については、OAuth.net および Web 承認プロトコル (OAuth) に関する記事を参照してください。

重要

Azure Active Directory (Azure AD) のサービスである Azure アクセス制御 (ACS) は、2018 年 11 月 7 日に廃止されます。 SharePoint アドイン モデルでは、(この廃止の影響を受けない) https://accounts.accesscontrol.windows.net ホスト名を使用しているため、この廃止による影響はありません。 詳細については、「SharePoint アドインに対する Azure アクセス制御の終了の影響」を参照してください。

一部のシナリオでは、アドインは、実行時に SharePoint のリソースにアクセスするためのアクセス許可を要求できます。つまり、アドインのインストール時ではなく実行時に、SharePoint のリソースにアクセスするためのアクセス許可を動的に要求できます。 この種のアドインは、必ずしも SharePoint から起動される必要はなく、また SharePoint にインストールされている必要さえありません。 たとえば、ネイティブ デバイス アドインや任意の Web サイトから起動されるアドインでもかまいません。また、実行時に SharePoint 上のリソースにアクセスする必要がある Office アプリケーションから起動された Office アドインであってもかまいません。

注:

この種類のアドインは、アドインでアクセスするリソースに対する管理権限を持つユーザーのみが実行できます。 たとえば、アドインが特定の Web サイトに対する読み取りアクセス許可のみを要求する場合、その Web サイトに対する読み取り権限を持っていても管理権限がないユーザーはこのアドインを実行できません。

この種のアドインが SharePoint にアクセスするには、販売者ダッシュボードか AppRegNew.aspx ページを介して、このアドインをまず登録する必要があります。 販売者ダッシュボードや AppRegNew.aspx を介したアドインの登録の詳細については、「SharePoint アドインを登録する」を参照してください。

登録したアドインは、セキュリティ プリンシパルとなり、ユーザーやグループと同じように ID が割り当てられます。 この ID は、アドイン プリンシパルと呼ばれます。 ユーザーやグループと同じように、アドイン プリンシパルにも特定のアクセス許可があります。 アドイン プリンシパルの詳細については、「SharePoint アドインを登録する」を参照してください。

このアドインを登録する場合、そのアドイン プリンシパルのクライアント ID、クライアント シークレット、アドイン ドメイン、およびリダイレクト URI を取得します。 この情報は、認証サーバーである Microsoft Azure Access Control Service (ACS) に登録されます。

実行時にアクセス許可を要求するアドインの認証コード OAuth フロー

このセクションでは、実行時にアクセス許可を要求する SharePoint アドインの OAuth 認証および承認フローの概要を示します。 ここで説明するフローは、認証コード フローと呼ばれます。 SharePoint 内から起動されないアドインが SharePoint 内のリソースにアクセスする方法について、以下に順を追って説明します。

注:

このフローの実行時に、アドイン、SharePoint、承認サーバー (ACS)、エンド ユーザーの間で一連の対話が必要になります。 このため、このフローでは、ACS と通信できるように、インターネットに接続された SharePoint Online または SharePoint ファームのいずれかが必要です。 インターネットに接続されていない SharePoint ファームでは、高信頼承認システムを使用する必要があります。

SharePoint とは別にホストされる Web アプリケーションまたはサービスが必要です。 アドインがデバイス アドインであったとしても、ACS に登録できる Web アプリケーションかサービスの URL が必要です。これは、Web コンポーネントが他の何にも使用されないとしても必要です。

わかりやすくするために、この記事ではアドインを Contoso.com という Web アプリケーションと仮定します。 アプリケーションは、SharePoint クライアント オブジェクト モデル (CSOM) または SharePoint REST API を使用して、SharePoint への呼び出しを行います。 アプリケーションが最初に SharePoint にアクセスしようとすると、SharePoint は Contoso.com アプリケーションに送信できる認証コードを ACS に要求します。 Contoso.com アプリケーションは、その認証コードを使用して ACS にアクセス トークンを要求します。 アクセス トークンを取得すると、Contoso.com アプリケーションは SharePoint への要求すべてにそのアクセス トークンを含めます。

フローの詳細な例

Contoso がオンラインで写真印刷サービスを提供しているとします。 写真を印刷したいユーザーがいます。 そのユーザーは Contoso 写真印刷サービスに同意して、写真ライブラリ内の写真を印刷します。この写真ライブラリは、そのユーザー自身が SharePoint Online サイト fabrikam.sharepoint.com で管理しているものです。

OAuth の概要

写真印刷アプリケーションが登録され、Contoso には、クライアント ID、クライアント シークレット、リダイレクト URI が設定されます。 Contoso がアドインの登録時に提供したリダイレクト URI は https://contoso.com/RedirectAccept.aspx です。 クライアント ID とクライアント シークレット情報は、写真編集アプリケーションの web.config ファイルに格納されます。 次に、クライアント ID とクライアント シークレット情報が web.config ファイルにどのように入力されているか、一例を示します。

<configuration>
  <appSettings>
    <add key="ClientId" value="c78d058c-7f82-44ca-a077-fba855e14d38 "/>
    <add key="ClientSecret" value="SbALAKghPXTjbBiLQZP+GnbmN+vrgeCMMvptbgk7T6w= "/>
  </appSettings>
</configuration>

認証コード フローの手順

認証コード フローの手順を次に示します。

ヒント

これらの手順は、TokenHelper.cs ファイルのメソッドを参照しています。 このマネージ コードはコンパイルされていないため、参照トピックはありません。 ただし、ファイルそのものには、それぞれのクラス、メンバー パラメーター、および戻り値について詳細なコメントが付いています。 これらの手順を読む際に参照できるよう、このファイルのコピーを開いておくことをお勧めします。

手順 1: クライアントがアプリケーションを開き、データを取得するために SharePoint サイトにそのアプリケーションを誘導します。

二人三脚 OAuth フロー - 手順 1

ユーザーが Contoso の写真印刷用 Web サイトにアクセスします。そのサイトの UI には、SharePoint Online サイトに保存されている写真をユーザーが印刷できることが表示されます。

この例では、その URL は https://contoso.com/print/home.aspx です。

ユーザーは、写真印刷アドインから写真コレクションの URL を入力するように求められます。 SharePoint Online サイトを指す URL として、「https://fabrikam.sharepoint.com/」をユーザーが入力します。

手順 2: アドインは SharePoint サイト承認 URL にリダイレクトします。

二人三脚 OAuth フロー - 手順 2

ユーザーが写真を取得するボタンを選択すると、Contoso 写真印刷アドインはブラウザーを https://fabrikam.sharepoint.com/ にリダイレクトします。このリダイレクトは HTTP 302 リダイレクト応答です。

Microsoft .NET を使用している場合、Response.Redirect はコードからリダイレクトを実行できるいくつかの方法の 1 つです。 プロジェクトで TokenHelper.cs ファイルを使用すると、コードはオーバーロードされた GetAuthorizationUrl メソッドを呼び出すことができます (3 つの引数を持つオーバーロードを使用)。 このメソッドは OAuthAuthorize.aspx リダイレクト URL を構成します。 または、コードで URL を手動で作成することもできます。

たとえば、GetAuthorizationUrl メソッドを呼び出し、プロジェクト内で TokenHelper.cs を使用して OAuthAuthorize.aspx リダイレクト URL を自動的に構成することを選択した場合、コードは次のようになります。

Response.Redirect(
  TokenHelper.GetAuthorizationUrl(
    sharePointSiteUrl.ToString(),
    "Web.Read List.Write",
    "https://contoso.com/RedirectAccept.aspx"
  )
);

TokenHelper.cs 内の GetAuthorizationUrl メソッドの 3 つのパラメーターのオーバーロードを確認すると、2 番目のパラメーターがアクセス許可のスコープ パラメーターであることがわかります。このパラメーターは、アドインが短縮形で要求する、スペースで区切られたアクセス許可のリストです。 アクセス許可のスコープの詳細については、「アクセス許可のスコープ エイリアスと OAuthAuthorize.aspx ページ」を参照してください。

3 番目のパラメーターは、このアドインの登録時に使用したのと同じリダイレクト URI である必要があります。 登録の詳細については、「SharePoint アドインを登録する」を参照してください。戻される文字列は、クエリ文字列パラメーターを含む URL です。 必要に応じて、OAuthAuthorize.aspx リダイレクト URL を手動で構成することもできます。 たとえば、この場合、Contoso 写真印刷アドインがユーザーをリダイレクトするURL は次のとおりです (読みやすくするために改行が追加されています)。

https://fabrikam.sharepoint.com/_layouts/15/OAuthAuthorize.aspx?
    client_id=client_GUID
    &scope=app_permissions_list
    &response_type=code
    &redirect_uri=redirect_uri

例に示すとおり、Contoso 写真印刷アドインは、OAuth クライアント ID とリダイレクト URI をクエリ文字列パラメーターとして Fabrikam サイトに送信します。 次に、サンプルのクエリ文字列値を指定した GET 要求の例を示します。 実際のターゲット URL は 1 行です。

GET /_layouts/15/OAuthAuthorize.aspx?client_id=c78d058c-7f82-44ca-a077-fba855e14d38&scope=list.read&response_type=code&redirect_uri=https%3A%2F%2Fcontoso%2Ecom%2Fredirectaccept.aspx HTTP/1.1
Host: fabrikam.sharepoint.com

別の同意ポップアップ ダイアログを表示する場合は、次のようにして、URL の構成にクエリ パラメーター IsDlg=1 を追加します。/oauthauthorize.aspx?IsDlg=1&client_id=c78d058c-7f82-44ca-a077-fba855e14d38&scope=list.read&response_type=code&redirect_uri=https%3A%2F%2Fcontoso%2Ecom%2Fredirectaccept.aspx

二人三脚 OAuth フロー - 手順 3

ユーザーが Fabrikam の SharePoint Online サイトにまだサインインしていない場合は、サインインするように求めるメッセージが表示されます。 ユーザーがサインインすると、SharePoint により HTML の同意ページが表示されます。 同意ページで、ユーザーは、Contoso 写真印刷アドインが要求しているアクセス許可をアドインに付与 (または拒否) するように求められます。 この例では、Fabrikam にあるユーザーの写真ライブラリに対する読み取りアクセスを、ユーザーはアドインに付与します。

手順 4: SharePoint は短時間有効な認証コードを ACS に要求します。

二人三脚 OAuth フロー - 手順 4

Fabrikam の SharePoint Online サイトは、このユーザーとアドインの組み合わせに固有の存続期間の短い (約 5 分の) 認証コードを作成するように ACS に要求します。 ACS は、その認証コードを Fabrikam のサイトに送信します。

手順 5: SharePoint Online サイトはアドインの登録済みリダイレクト URL にリダイレクトし、認証コードをアドインに渡します。

二人三脚 OAuth フロー - 手順 5

Fabrikam の SharePoint Online サイトは、HTTP 302 応答によってブラウザーを元の Contoso にリダイレクトします。 このリダイレクト URL 構成には、写真印刷アドインの登録時に指定されたリダイレクト URI が使用されます。 また、この URL 構成には認証コードがクエリ文字列として含まれています。

リダイレクト URL は次のようになります。https://contoso.com/RedirectAccept.aspx?code=[authcode]

手順 6: アドインは認証コードを使用して ACS にアクセス トークンを要求します。ACS はその要求を検証し、認証コードを無効にしてから、アクセス トークンと更新トークンをアドインに送信します。

二人三脚 OAuth フロー - 手順 6

Contoso はクエリ パラメーターから認証コードを取得し、アクセス トークンの要求時に、認証コードに加えてクライアント ID とクライアント シークレットを ACS に送信します。

マネージ コードと SharePoint CSOM、TokenHelper.cs ファイルを使用している場合、ACS への要求を行うメソッドは GetClientContextWithAuthorizationCode です。 この場合、コードは次のようになります (ここで authCode 、承認コードが割り当てられている変数)。

TokenHelper.GetClientContextWithAuthorizationCode(
  "https://fabrikam.sharepoint.com/",
  "00000003-0000-0ff1-ce00-000000000000",
  authCode,
  "1ee82b34-7c1b-471b-b27e-ff272accd564",
  new Uri(Request.Url.GetLeftPart(UriPartial.Path))
);

TokenHelper.cs ファイルを確認すると、GetClientContextWithAuthorizationCode メソッドの 2 番目のパラメーターは targetPrincipalName になっています。 SharePoint にアクセスするアドインの場合、この値は必ず、定数の 00000003-0000-0ff1-ce00-000000000000 です。 また、GetClientContextWithAuthorizationCode からの呼び出しの階層をトレースすると、web.config ファイルからクライアント ID とシークレットを取得していることもわかります。

ACS は Contoso の要求を受け取ると、クライアント ID、クライアント シークレット、リダイレクト URI、認証コードを検証します。 これらがすべて有効であれば、ACS はその認証コードを無効にし (認証コードは 1 回だけ使用できます)、更新トークンとアクセス トークンを作成して、これらのトークンを Contoso に返します。 Contoso アプリケーションは、このアクセス トークンを後の要求で再利用するためにキャッシュできます。 既定で、アクセス トークンの有効期限は約 12 時間です。

個々のアクセス トークンは、元の承認要求で指定されたユーザー アカウントに固有で、その要求で指定されたサービスに対するアクセスのみを付与します。 アドインは、アクセス トークンを安全に格納する必要があります。 Contoso アプリケーションは、更新トークンもキャッシュできます。 既定で、更新トークンの有効期限は 6 か月間です。 アクセス トークンの有効期限が切れた場合は、いつでも更新トークンを使用して ACS から新しいアクセス トークンを取得できます。

トークンの詳細については、「プロバイダー向けのホスト型の低信頼 SharePoint アドインでセキュリティ トークンを処理する」を参照してください。

手順 7: これで、アドインはアクセス トークンを使用して SharePoint サイトにデータを要求し、それをユーザーに表示できるようになります。

二人三脚 OAuth フロー - 手順 7

Contoso はアクセス トークンを使用して SharePoint への REST API 呼び出しまたは CSOM 要求を行うことができます。このとき、OAuth アクセス トークンを HTTP Authorization ヘッダーで渡します。 SharePoint は Contoso が要求した情報を返します。

この要求の作成方法の詳細については、「プロバイダー向けのホスト型の低信頼 SharePoint アドインでセキュリティ トークンを処理する」を参照してください。

アクセス許可のスコープ エイリアスと OAuthAuthorize.aspx ページ

このセクションでは、「SharePoint でのアドインのアクセス許可」の記事を理解していることを前提としています。 表 1 に、その記事に示すものと同じアドイン アクセス許可要求スコープの URI を示します。ただし、この表には、"スコープ エイリアス" という列が 1 つ追加されています。また、実行時に SharePoint のリソースへのアクセス許可を要求するアドインは、フル コントロール権限を要求することはできないため、"使用可能な権限" 列でフル コントロール権限は使用可能として記載されていません。

"スコープ エイリアス" 列に示した値は、"スコープ URI" 列にある対応する値の短縮形です。 これらのエイリアスは、実行時に SharePoint のリソースにアクセスするためのアクセス許可を要求するアドインによってのみ使用されます。 (スコープ URI 値は、SharePoint から起動されるアドインのアドイン マニフェストで使用されます。これらのアドインは、アドインのインストール中にアクセス許可を要求します)。

これらのスコープ エイリアスは、OAuthAuthorize.aspx リダイレクト ページを使用するコンテキストでのみ使用されます。 前のセクションで説明した OAuth フローの手順 2 で示したように、アドインでマネージ コードを使用している場合、プロジェクト内で TokenHelper.csGetAuthorizationUrl メソッドを呼び出すときに、これらのエイリアスが使用されます。 別の例を次に示します。

Response.Redirect(TokenHelper.GetAuthorizationUrl(
    sharePointSiteUrl.ToString(),
    "Web.Read List.Write ",
    "https://contoso.com/RedirectAccept.aspx ")
);

scope パラメーターの値 Web.Read List.Write は、スコープ エイリアスを使用してアクセス許可を要求する方法の一例です。 scope パラメーターには、アクセス許可のスコープと権限の要求をスペースで区切って指定します。

マネージ コードを使用していない場合、スコープ エイリアスは、リダイレクト URL の scope フィールドで使用されます。 次に、例を示します。

https://fabrikam.sharepoint.com/_layout/15/OAuthAuthorize.aspx?client_id=c78d058c-7f82-44ca-a077-fba855e14d38&scope=list.write&response_type=code&redirect_uri=https%3A%2F%2Fcontoso%2Ecom%2Fredirectaccept.aspx

注:

スコープについては、「SharePoint でのアドインのアクセス許可」を参照してください。

表 1. SharePoint アドインのアクセス許可要求のスコープ URI とそれに対応するエイリアス

スコープ URI スコープ エイリアス 使用可能な権限
https://sharepoint/content/sitecollection Site Read、Write、Manage
https://sharepoint/content/sitecollection/web Web Read、Write、Manage
https://sharepoint/content/sitecollection/web/list List Read、Write、Manage
https://sharepoint/content/tenant AllSites Read、Write、Manage
https://sharepoint/bcs/connection なし (現在サポートなし) Read
https://sharepoint/search Search QueryAsUserIgnoreAppPrincipal
https://sharepoint/projectserver ProjectAdmin Manage
https://sharepoint/projectserver/projects Projects Read、Write
https://sharepoint/projectserver/projects/project Project Read、Write
https://sharepoint/projectserver/enterpriseresources ProjectResources Read、Write
https://sharepoint/projectserver/statusing ProjectStatusing SubmitStatus
https://sharepoint/projectserver/reporting ProjectReporting Read
https://sharepoint/projectserver/workflow ProjectWorkflow Elevate
https://sharepoint/social/tenant AllProfiles Read、Write、Manage
https://sharepoint/social/core Social Read、Write、Manage
https://sharepoint/social/microfeed Microfeed Read、Write、Manage
https://sharepoint/taxonomy TermStore Read、Write

リダイレクト URI とサンプルのリダイレクト ページ

実行時にアクセス許可を要求するアドインによって使用されるリダイレクト URI は、認証コードがクエリ パラメーターとして格納され、同意が付与された後で、SharePoint によりブラウザーがリダイレクトされる URI です。 OAuth フローの手順 2 に、GetAuthorizationUrl メソッドの呼び出しでこの URI がハードコーディングされている例が示されています。 また、次の例に示すように、ASP.NET アドインで web.config ファイルにリダイレクト URI を格納することもできます。

<configuration>
  <appSettings>
    <add key="RedirectUri" value="https://contoso.com/RedirectAccept.aspx" />
  </appSettings>
<configuration>

値は WebConfigurationManager.AppSettings.Get("RedirectUri") の呼び出しを使用して取得できます。

RedirectUri のエンドポイントは、クエリ パラメーターから認証コードを取得し、アクセス トークンを取得するためにそのコードを使用します。アクセス トークンは SharePoint へのアクセスに使用できます。 通常、このエンドポイントは、SharePoint へのアクセスを最初に試みたページ、コントローラー メソッド、または Web メソッドと同じものです。 ただし、このエンドポイントが、認証トークンのみを取得して、別のページまたはメソッドにリダイレクトするページやメソッドの場合もあります。 特別なページまたはメソッドは、認証トークンを渡したりキャッシュしたりできます。 (有効期限は約 5 分です)。また、認証トークンを使用してアクセス トークンを取得し、キャッシュすることもできます。

重要

RedirectUri は、AppRegNew.aspx ページでアプリを作成したときにリストされたものと同じエンドポイントでなければなりません。

ASP.NET アプリケーションのそのようなページのコード ビハインドの例を以下に示します。 このコードについては、次の点に注意してください。

  • Office Developer Tools for Visual Studio によって生成される TokenHelper.cs ファイルを使用します。
  • コードは、認証コードを保持する「コード」クエリ パラメータがあることを前提としています。 ページは SharePoint によってのみ呼び出され、認証コードを渡す場合にのみ呼び出されるため、これは安全です。
  • CSOM クライアント コンテキスト オブジェクトを使用して SharePoint にアクセスしますが、そのオブジェクトをサーバーにキャッシュして、別のページにリダイレクトできます。
  • GetClientContextWithAuthorizationCode メソッドは、認証コードを使用してアクセス コードを取得します。 次に、SharePoint クライアント コンテキスト オブジェクトを作成し、ExecutingWebRequest イベントのオブジェクトのハンドラーを変更して、ハンドラーが SharePoint へのすべての要求にアクセス トークンを含めるようにします。 アクセス トークンは、実際には、オブジェクトの内部にキャッシュされます。
  • GetClientContextWithAuthorizationCode メソッドは、リダイレクト URL を rUrl パラメーターで ACS に送信しますが、ACS は認証コードが盗まれた場合にそれを ID の形式として使用します。 ACS は再度リダイレクトするためにこれを利用するこはしないので、このコードが自分自身にエンドレスでリダイレクトすることはありません。
  • このコードでは、期限切れのアクセス トークンを処理するためのプロビジョニングは実行されません。 クライアント コンテキスト オブジェクトは、一度作成されると同じアクセス トークンを使用し続けます。 更新トークンはまったく使用しません。 これは、アクセス トークンの有効期間より短いセッションでのみ使用されるアドインに適した戦略です。

更新トークンを使用して新しいアクセス トークンを取得するより複雑な例は、次のセクションを参照してください。

public partial class RedirectAccept : System.Web.UI.Page
{
  protected void Page_Load(object sender, EventArgs e)
  {
    string authCode = Request.QueryString["code"];
    Uri rUri = new Uri("https://contoso.com/RedirectAccept.aspx");

    using (ClientContext context = TokenHelper.GetClientContextWithAuthorizationCode(
        "https://fabrikam.sharepoint.com/",
        "00000003-0000-0ff1-ce00-000000000000",
        authCode,
        "1ee82b34-7c1b-471b-b27e-ff272accd564".
        rUri))
    {
      context.Load(context.Web);
      context.ExecuteQuery();

      Response.Write("<p>" + context.Web.Title + "</p>");
    }
  }
}

SharePoint にアクセスするページのコード ビハインドのサンプル

Default.aspx ページのコード ビハインドを次に示します。 このページは、Default ページがアドインの開始ページであり、アドインに対して登録されたリダイレクト URL でもあるシナリオを想定しています。 このコードについては、次の点に注意してください。

  • Page_Load メソッドは、まずクエリ文字列内に認証コードがあるか確認します。 SharePoint によってブラウザーがページにリダイレクトされた場合は、認証コードがあるはずです。 認証コードがある場合、コードはそれを使用して新しい更新トークンを取得し、複数のセッションにわたって持続する永続キャッシュにその更新トークンをキャッシュします。

  • このメソッドでは、そのキャッシュに更新トークンがあるかが次に確認されます。

    • ない場合は、SharePoint に必要な権限 (Web スコープでの書き込み権限) を通知し、SharePoint に認証コードを要求することで取得します。 ユーザーは権限を付与するように求められ、付与された場合、SharePoint は ACS から認証コードを取得し、それをこの同じページへのリダイレクトのクエリ パラメータとして返信します。
    • キャッシュされた更新トークンがある場合、メソッドはそれを利用して、ACS からアクセス トークンを直接取得します。 この記事の前のセクションの終わりの例で示したとおり、アクセス トークンは SharePoint クライアント コンテキスト オブジェクトの作成に使用されます。 キャッシュされた更新トークンを使用して ACS からアクセス トークンを直接取得することにより、セッションの開始時に SharePoint に対して追加のネットワーク呼び出しを行わずに済みます。これにより、更新トークン キャッシュの有効期限内でアドインを再実行する場合、起動がより高速になります。
  • 前のセクションの終わりの例と同じように、このコードでは、期限切れのアクセス トークンを処理するためのプロビジョニングは実行されません。 クライアント コンテキスト オブジェクトは、一度作成されると同じアクセス トークンを使用し続けます。 アクセス トークンの有効期限切れから保護する 1 つの方法は、更新トークンに加えてアクセス トークンもキャッシュすることです。 以下のコードを変更し、有効期限が切れていないアクセス トークンがキャッシュにない場合にのみ、コードが GetAccessToken メソッドを呼び出すようにします。

    ただし、更新トークンはクライアント側の Cookie などにもキャッシュできますが、アクセス トークンについては、セキュリティ上の理由からサーバー側のキャッシュにのみ入れる必要があります。 更新トークンは ACS によって暗号化され、ACS でのみ非暗号化できます。 しかし、アクセス トークンは単にエンコード (Base 64 エンコード) されているだけであり、man-in-the-middle 攻撃により容易にデコードされてしまいます。

  • このコードで参照される TokenCache クラスについては、このセクションで後述します。

Default.aspx ページのコード ビハインド

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint.Samples;
using Microsoft.SharePoint.Client;

namespace DynamicAppPermissionRequest
{
  public partial class Default : System.Web.UI.Page
  {
    protected void Page_Load(object sender, EventArgs e)
    {
      Uri sharePointSiteUrl = new Uri("https://fabrikam.sharepoint.com/print/");

      if (Request.QueryString["code"] != null)
      {
        TokenCache.UpdateCacheWithCode(Request, Response, sharePointSiteUrl);
      }

      if (!TokenCache.IsTokenInCache(Request.Cookies))
      {
        Response.Redirect(TokenHelper.GetAuthorizationUrl(sharePointSiteUrl.ToString(), "Web.Write"));
      }
      else
      {
        string refreshToken = TokenCache.GetCachedRefreshToken(Request.Cookies);
        string accessToken =
        TokenHelper.GetAccessToken(
                    refreshToken,
                    "00000003-0000-0ff1-ce00-000000000000",
                    sharePointSiteUrl.Authority,
                    TokenHelper.GetRealmFromTargetUrl(sharePointSiteUrl)).AccessToken;

        using (ClientContext context =
                TokenHelper.GetClientContextWithAccessToken(sharePointSiteUrl.ToString(),
                                                            accessToken))
        {
          context.Load(context.Web);
          context.ExecuteQuery();

          Response.Write("<p>" + context.Web.Title + "</p>");
        }
      }
    }
  }
}

次に、前のサンプル コードが呼び出すトークン キャッシュ モジュールのコード例を示します。 これはキャッシュとして Cookie を使用しています。 キャッシュには、別のオプションもあります。 詳細については、「プロバイダー向けのホスト型の低信頼 SharePoint アドインでセキュリティ トークンを処理する」を参照してください。

トークン キャッシュ モジュールのコード例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.SharePoint.Samples;

namespace DynamicAppPermissionRequest
{
  public static class TokenCache
  {
    private const string REFRESH_TOKEN_COOKIE_NAME = "RefreshToken";

    public static void UpdateCacheWithCode(HttpRequest request,
                                            HttpResponse response,
                                            Uri targetUri)
    {
      string refreshToken =
          TokenHelper.GetAccessToken(
              request.QueryString["code"],
              "00000003-0000-0ff1-ce00-000000000000",
              targetUri.Authority,
              TokenHelper.GetRealmFromTargetUrl(targetUri),
              new Uri(request.Url.GetLeftPart(UriPartial.Path))
          ).RefreshToken;
      SetRefreshTokenCookie(response.Cookies, refreshToken);
      SetRefreshTokenCookie(request.Cookies, refreshToken);
    }

    internal static string GetCachedRefreshToken(HttpCookieCollection requestCookies)
    {
      return GetRefreshTokenFromCookie(requestCookies);
    }

    internal static bool IsTokenInCache(HttpCookieCollection requestCookies)
    {
      return requestCookies[REFRESH_TOKEN_COOKIE_NAME] != null;
    }

    private static string GetRefreshTokenFromCookie(HttpCookieCollection cookies)
    {
      if (cookies[REFRESH_TOKEN_COOKIE_NAME] != null)
      {
        return cookies[REFRESH_TOKEN_COOKIE_NAME].Value;
      }
      else
      {
        return null;
      }
    }

    private static void SetRefreshTokenCookie(HttpCookieCollection cookies, string refreshToken)
    {
      if (cookies[REFRESH_TOKEN_COOKIE_NAME] != null)
      {
        cookies[REFRESH_TOKEN_COOKIE_NAME].Value = refreshToken;
      }
      else
      {
        HttpCookie cookie = new HttpCookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken);
        cookie.Expires = DateTime.Now.AddDays(30);
        cookies.Add(cookie);
      }
    }
  }
}

関連項目