シングル サインオンを使用する Node.js Office アドインを作成する (プレビュー)Create a Node.js Office Add-in that uses single sign-on (preview)

ユーザーは、このサインイン プロセスを利用してユーザーを承認する Office および Office Web アドインにサインインできます。こうして承認されたユーザーは、アドインと Microsoft Graph への 2 度目のサインオンの必要がなくなります。概要については、「Office アドインで SSO を有効化する」を参照してください。Users can sign in to Office, and your Office Web Add-in can take advantage of this sign-in process to authorize users to your add-in and to Microsoft Graph without requiring users to sign in a second time. For an overview, see Enable SSO in an Office Add-in.

この記事では、Node.js と Express を使用して作成したアドインで、シングル サインオン (SSO) を有効化するプロセスについて手順を追って説明します。This article walks you through the process of enabling single sign-on (SSO) in an add-in that is built with Node.js and Express.


ASP.NET ベースのアドインに関する同様の記事については、「シングル サインオンを使用する ASP.NET Office アドインを作成する」を参照してください。For a similar article about an ASP.NET-based add-in, see Create an ASP.NET Office Add-in that uses single sign-on.


  • Node および npm、バージョン 6.9.4 以降Node and npm, version 6.9.4 or later

  • Git バッシュ (またはその他の Git クライアント)Git Bash (or another git client)

  • TypeScript バージョン 2.2.2 以降TypeScript version 2.2.2 or later

  • Office 2016 バージョン 1708、ビルド 8424.nnnn 以降 (「クイック実行」と呼ばれることもある Office 365 のサブスクリプション バージョン)Office 2016, Version 1708, build 8424.nnnn or later (the Office 365 subscription version, sometimes called “Click to Run”)

    このバージョンを入手するには、Office Insider への参加が必要になることがあります。詳細については、「Office Insider」を参照してください。You might need to be an Office Insider to get this version. For more information, see Be an Office Insider.

スタート プロジェクトをセットアップするSet up the starter project

  1. Office Add-in NodeJS SSO」にあるリポジトリを複製またはダウンロードします。Clone or download the repo at Office Add-in NodeJS SSO.


    サンプルには 3 つのバージョンがあります。There are two versions of the sample:

    • [Before] フォルダーはスタート プロジェクトです。SSO や承認に直接関連しない UI などの側面は、既に完了しています。この記事で後述する各セクションでは、これを完成させるための手順を順に説明します。The Before folder is a starter project. The UI and other aspects of the add-in that are not directly connected to SSO or authorization are already done. Later sections of this article walk you through the process of completing it.
    • このサンプルの [Completed] バージョンは、この記事の手順を完了したときに得られるアドインと同様のものですが、完成済みのプロジェクトには、この記事のテキストと重複するコード コメントが含まれています。完成済みのバージョンを使用する場合は、この記事の手順をそのまま実行しますが、[Before] を [Completed] に置き換えて、「クライアント側のコードを作成する」と「サーバー側のコードを作成する」のセクションを省略してください。The Completed version of the sample is just like the add-in that you would have if you completed the procedures of this article, except that the completed project has code comments that would be redundant with the text of this article. To use the completed version, just follow the instructions in this article, but replace "Before" with "Completed" and skip the sections Code the client side and Code the server side.
    • 完成版のマルチ テナント バージョンは、マルチ テナント機能をサポートする完成版のサンプルです。The Completed Multitenant version is a completed sample that supports multitenancy. SSO を使用して異なるドメインから Microsoft アカウントをサポートする場合は、このサンプルを表示します。Explore this sample if you intend to support Microsoft accounts from different domains with SSO.
  2. [Before] フォルダー内で Git bash コンソールを開きます。Open a Git bash console in the Before folder.

  3. コンソールで npm install を入力して、package.json ファイル内のアイテム化されたすべての依存関係をインストールします。Enter npm install in the console to install all of the dependencies itemized in the package.json file.

  4. コンソールで npm run build を入力して、プロジェクトをビルドします。Enter npm run build in the console to build the project.


    いくつかの使用されていない変数が宣言されているという、ビルド エラーが発生することがあります。これらのエラーは無視してください。これらは、後で追加する一部のコードが見つからないという「Before」バージョンのサンプルの副作用です。You may see some build errors saying that some variables are declared but not used. Ignore these errors. They are a side effect of the fact that the "Before" version of the sample is missing some code that will be added later.

Azure AD v2.0 エンドポイントにアドインを登録するRegister the add-in with Azure AD v2.0 endpoint

次の手順は、複数の場所で使用できるように一般的に記述されています。The following instruction are written generically so they can be used in multiple places. この記事では、以下を実行します:For this ariticle do the following:

  • プレースホルダー $ ADD-IN-NAME $“Office-Add-in-NodeJS-SSO に置き換えます。Replace the placeholder $ADD-IN-NAME$ with “Office-Add-in-NodeJS-SSO.
  • プレースホルダー $ FQDN-WITHOUT-PROTOCOL$localhost:3000 に置き換えます。Replace the placeholder $FQDN-WITHOUT-PROTOCOL$ with localhost:3000.
  • [アクセス許可を選択] ダイアログでアクセス許可を指定するときに、次のアクセス許可のボックスをオンにします。When you specify permissions in the Select Permissions dialog, check the boxes for the following permissions. 実際にアドイン自体に必要なのは最初のものだけですが、 profile Office ホストがアドインの Web アプリケーションに対してトークンを取得するために、アクセス許可が必要です。Only the first is really required by your add-in itself; but the profile permission is required for the Office host to get a token to your add-in web application.
    • Files.Read.AllFiles.Read.All
    • profileprofile
  1. https://apps.dev.microsoft.com/にナビゲートします。Navigate to https://apps.dev.microsoft.com/

  2. ダイアログが表示されたら、*** 管理者*** の資格情報を使用して Office 365 テナントにサインインします。Sign-in with the admin credentials to your Office 365 tenancy. For example, MyName@contoso.onmicrosoft.com たとえば、MyName@contoso.onmicrosoft.com のようにしますFor example, MyName@contoso.onmicrosoft.com

  3. [アプリの追加] をクリックします。Click Add an app.

  4. 表示されたら、[$ADD-IN-NAME$] をアプリ名として入力してから [アプリケーションの作成] をクリックします。When prompted, use “Office-Add-in-ASPNET-SSO” as the app name, and then press Create application.

  5. アプリの構成ページが開いたら、[アプリケーション ID] をコピーして保存します。これは、この後の手順で使用します。When the configuration page for the app opens, copy the Application Id and save it. You'll use it in a later procedure.


    この ID は、Office ホスト アプリケーション (たとえば、PowerPoint、Word、Excel) などの別のアプリケーションが、このアプリケーションへの承認されたアクセスを求めるときの「対象ユーザー」値になります。また、そのアプリケーションが Microsoft Graph への承認されたアクセスを求めるときには、このアプリケーションの「クライアント ID」になります。This ID is the “audience” value when other applications, such as the Office host application (e.g., PowerPoint, Word, Excel), seek authorized access to the application. It is also the “client ID” of the application when it, in turn, seeks authorized access to Microsoft Graph.

  6. [アプリケーション シークレット] セクションで、[新しいパスワードを生成する] をクリックします。新しいパスワード (「アプリケーション シークレット」とも呼びます) が示されたポップアップ ダイアログが開きます。このパスワードをすぐにコピーして、アプリケーション ID と共に保存します。 これは、この後の手順で必要になります。その後で、ダイアログを閉じます。In the Application Secrets section, press Generate New Password. A popup dialog opens with a new password (also called an “app secret”) displayed. Copy the password immediately and save it with the application ID. You'll need it in a later procedure. Then close the dialog.

  7. [プラットフォーム] セクションで、[プラットフォームの追加] をクリックします。In the Platforms section, click Add Platform.

  8. 開いたダイアログで、[Web API] を選択します。In the dialog that opens, select Web API.

  9. アプリケーション ID URI は、"api://$App ID GUID$"のフォームで生成されています。An Application ID URI has been generated of the form “api://$App ID GUID$”. [$FQDN-WITHOUT-PROTOCOL$] を二重のスラッシュと GUID の間に(スラッシュ「/」を末尾に追加するかたちで)挿入します。Insert the $FQDN-WITHOUT-PROTOCOL$ (with a forward slash "/" appended to the end) between the double forward slashes and the GUID. ID 全体には api://$FQDN-WITHOUT-PROTOCOL$/$App ID GUID$ というフォームが必要です。例えば、 api://localhost:6789/c6c1f32b-5e55-4997-881a-753cc1d563b7のようにします。The entire ID should have the form api://$FQDN-WITHOUT-PROTOCOL$/$App ID GUID$; for example api://localhost:6789/c6c1f32b-5e55-4997-881a-753cc1d563b7.


    ドメインを既に所有している場合に、所有しているというエラーが表示された場合は、 [クイックスタート」に従います。これは、Azure Active Directory にカスタムドメイン名を追加 し、 それを登録してから、この手順を繰り返します。If you get an error saying that the domain is already owned, but you own it, follow the procedure at Quickstart: Add a custom domain name to Azure Active Directory to register it, and then repeat this step. (Office 365 テナントに管理者の資格情報でサインインしていない場合、このエラーも発生する可能性があります。(This error can also occur if you are not signed in with credentials of an admin in the Office 365 tenancy. 手順 2 を参照してください。See step 2. サインアウトして管理者の資格情報でもう一度サインインし、手順 3 から手順を繰り返します。)Sign out and sign in again with admin credentials and repeat the process from step 3.)


    ** アプリケーション ID URI** のすぐ下の** スコープ ** 名のドメイン部分は、/access_as_user を末尾に追加するかたちで、一致するように自動的に変更されます。例えば、 api://localhost:6789/c6c1f32b-5e55-4997-881a-753cc1d563b7/access_as_userのようになります。The domain part of the Scope name just below the Application ID URI will automatically change to match.

  10. [事前承認済みアプリケーション] セクションで、アドインの Web アプリケーションに対して承認するアプリケーションを特定します。In the Pre-authorized applications section, you identify the applications that you want to authorize to your add-in's web application. 次のそれぞれの ID を事前承認する必要があります。Each of the following IDs needs to be pre-authorized. 1 つの ID を入力するたびに、新しい空のテキスト ボックスが表示されます。Each time you enter one, a new empty textbox appears. (GUID のみを入力してください。)(Enter only the GUID.)

    • d3590ed6-52b3-4102-aeff-aad2292ab01c (Microsoft Office)d3590ed6-52b3-4102-aeff-aad2292ab01c (Microsoft Office)
    • 57fb890c-0dab-4253-a5e0-7188c88b2bb4 (Office Online)57fb890c-0dab-4253-a5e0-7188c88b2bb4 (Office Online)
    • bc59ab01-8403-45c6-8796-ac3ef710b3e3 (Office Online)bc59ab01-8403-45c6-8796-ac3ef710b3e3 (Office Online)
  11. それぞれの** [アプリケーション ID]** の横の** [スコープ]** ドロップダウンを開いて、api://$FQDN-WITHOUT-PROTOCOL$/$App ID GUID$/access_as_user のボックスをオンにします。Open the Scope drop-down beside each Application ID and check the box for api://$FQDN-WITHOUT-PROTOCOL$/$App ID GUID$/access_as_user.

  12. [プラットフォーム] セクションの上部にある [プラットフォームの追加] を再度クリックして、[Web] を選択します。Near the top of the Platforms section, click Add Platform again and select Web.

  13. ** [プラットフォーム]** の下側の新しい ** [Web]** セクションで、[リダイレクト URL] として https://$FQDN-WITHOUT-PROTOCOL$ を入力します。In the new Web section under Platforms, enter the following as a Redirect URL: https://$FQDN-WITHOUT-PROTOCOL$.

  14. [Microsoft Graph のアクセス許可] セクションを下にスクロールして、[委任されたアクセス許可] サブセクションを表示します。[追加] ボタンを使用して、[アクセス許可の選択] ダイアログを開きます。Scroll down to the Microsoft Graph Permissions section, the Delegated Permissions subsection. Use the Add button to open a Select Permissions dialog.

  15. ダイアログ ボックスで、 [profile] ボックスおよびアドインに必要な他の AAD および Microsoft Graph 許可をチェックします。In the dialog box, check the boxes for profile and any other AAD and Microsoft Graph permissions that your add-in needs. 次に、例を示します。The following are examples:

    • Files.Read.AllFiles.Read.All
    • offline_accessoffline_access
    • openidopenid
    • profileprofile


      User.Read アクセス許可は既定でリストされています。The User.Read permission may already be listed by default. 必要でないアクセス許可は依頼しない方がよいため、アドインで実際に必要でなければ、このアクセス許可のチェックボックスをオフにすることをお勧めします。It is a good practice not to ask for permissions that are not needed, so we recommend that you uncheck the box for this permission.

  16. ダイアログの下部にある [OK] をクリックします。At the bottom of the dialog, click OK.

  17. 登録ページの下部にある [保存] をクリックします。At the bottom of the registration page, click Save.


この手順が必要とされるのは、アドインを開発しているときだけです。実際に運用するアドインを AppSource またはアドイン カタログに展開した場合、インストール時に、各ユーザーが個別にそのアドインを信頼するか、管理者が組織のために同意することになります。This procedure is only needed when you're developing the add-in. When your production add-in is deployed to AppSource or an add-in catalog, users will individually trust it or an admin will consent for organization at installation.

この手順は、アドインを登録したに実行してください。Carry out this procedure after you have registered the add-in.

  1. 次に示す文字列内で、プレースホルダー "{application_ID}" を、アドインの登録時にコピーしたアプリケーション ID に置き換えます。 https://login.microsoftonline.com/common/adminconsent?client_id={application_ID}&state=12345In the following string, replace the placeholder “{application_ID}” with the Application ID that you copied when you registered your add-in: https://login.microsoftonline.com/common/adminconsent?client_id={application_ID}&state=12345

  2. そうしてできた URL をブラウザーのアドレス バーに貼り付けて、そこに移動します。Paste the resulting URL into a browser address bar and navigate to it.

  3. ダイアログが表示されたら、管理者の資格情報を使用して Office 365 テナントにサインインします。When prompted, sign in with the admin credentials to your Office 365 tenancy.

  4. その後、Microsoft Graph データにアクセスするためのアクセス許可をアドインに付与するように求めるダイアログが表示されます。[承諾] をクリックします。You are then prompted to grant permission for your add-in to access your Microsoft Graph data. Click Accept.

  5. ブラウザのウィンドウ (タブ) は、アドインの登録時に指定した リダイレクトURL にリダイレクトされます。The browser window/tab is then redirected to the Redirect URL that you specified when you registered the add-in, so the home page of the add-in opens in the browser. アドインの Web アプリケーションを実行している場合は、アドインのホームページがブラウザで開きます。それ以外の場合は、404 エラーが発生します。If the add-in's web application is running, the home page of the add-in opens in the browser; otherwise, you'll get a 404 error. しかし、ブラウザがホームページを開こうとしたという事実は、同意がうまく与えられたことを意味します。But the fact that the browser attempted to open the home page means that consent was successfully granted.


開発者向け O365 テナントを使用している場合は、この手順をベスト プラクティスとしてお勧めします。We recommend this procedure as a best practice if you are using a Developer O365 tenant. ただし、お好みに応じて、開発中の SSO アドインをサイドローディングして、ユーザーに同意書を要求することもできます。However, if you prefer, it is possible to sideload an SSO add-in under development and prompt the user with a consent form. 詳細については、 Windows のサイドローディング および Office Online のサイドローディング を参照してください。For more information, see Sideload on Windows and Sideload on Office Online.

アドインを構成するConfigure the add-in

  1. コード エディターで、src\server.ts ファイルを開きます。先頭近くに、AuthModule クラスのコンストラクターの呼び出しがあります。コンストラクターには、値を割り当てる必要がある、文字列のパラメーターがあります。In your code editor, open the src\server.ts file. Near the top there is a call to a constructor of an AuthModule class. There are some string parameters in the constructor to which you need to assign values.

  2. client_id プロパティの場合は、アドインの登録時に保存したアプリケーション IDでプレースホルダーの {client GUID} を置き換えます。For the client_id property, replace the placeholder {client GUID} with the application secret that you saved when you registered the add-in. 完了したら、GUID を単一引用符で囲んでください。When you are done, there should just be a GUID in single quotation marks. "{}" 符号は使用しないでください。There should not be any "{}" characters.

  3. client_secret プロパティの場合は、アドインの登録時に保存したアプリケーション シークレットでプレースホルダーの {client secret} を置き換えます。For the client_secret property, replace the placeholder {client secret} with the application secret that you saved when you registered the add-in.

  4. プロパティの場合は、アドインの登録時に保存したアプリケーション ID でプレースホルダーの {audience GUID} を置き換えます。(client_id プロパティに割り当てた値とまったく同じになります)。audienceFor the audience property, replace the placeholder {audience GUID} with the application ID that you saved when you registered the add-in. (The very same value that you assigned to the client_id property.)

  5. プロパティに割り当てられた文字列には、プレースホルダー {O365 tenant GUID} が表示されます。issuerIn the string assigned to the issuer property, you will see the placeholder {O365 tenant GUID}. これを Office 365 テナント ID に置き換えます。Replace this with the Office 365 tenancy ID. Office 365テナントIDを見つける 」にあるいずれかの方法を使用して、IDを取得します。Use one of the methods in Find your Office 365 tenant ID to obtain it. 完了したら、 issuer プロパティの値は次のようになります。When you are done, the issuer property value should look something like this:


  6. AuthModule コンストラクターのその他の値は変更しないでください。Leave the other parameters in the AuthModule constructor unchanged. ファイルを保存して閉じます。Save and close the file.

  7. プロジェクトのルートにある、アドイン マニフェスト ファイル「Office-Add-in-NodeJS-SSO.xml」を開きます。In the root of the project, open the add-in manifest file “Office-Add-in-NodeJS-SSO.xml”.

  8. ファイルの最後までスクロールします。Scroll to the bottom of the file.

  9. 最後の </VersionOverrides> タグの直前に、次に示すマークアップが見つかります。Just above the end </VersionOverrides> tag, you will find the following markup:

      <Id>{application_GUID here}</Id>
      <Resource>api://localhost:3000/{application_GUID here}</Resource>
  10. このマークアップ内の両方の場所のプレースホルダー “{application_GUID here}” を、アドインの登録時にコピーしたアプリケーション ID に置き換えます。Replace the placeholder “{application_GUID here}” in both places in the markup with the Application ID that you copied when you registered your add-in. ("{}" は ID の一部ではないので、含めないでください。) これは、web.config の ClientID と Audience に使用したのと同じ ID です。(The "{}" are not part of the ID, so don't include them.) This is the same ID you used in for the ClientID and Audience in the web.config.


    • [リソース] の値は、アドインの登録に Web API プラットフォームを追加したときに設定した [アプリケーション ID URI] です。The Resource value is the Application ID URI you set when you added the Web API platform to the registration of the add-in.
    • [範囲] セクションは、アドインが AppSource から販売された場合に、同意ダイアログ ボックスを生成するためにのみ使用します。The Scopes section is used only to generate a consent dialog box if the add-in is sold through AppSource.
  11. ファイルを保存して閉じます。Save and close the file.

クライアント側のコードを作成するCode the client side

  1. [public] フォルダー内の program.js ファイルを開きます。これには、一部のコードが既に含まれています。Open the program.js file in the public folder. It already has some code in it:

    • メソッドへの割り当てが、getGraphAccessTokenButton ボタン クリック イベントへのハンドラーの割り当てになります。Office.initializeAn assignment to the Office.initialize method that, in turn, assigns a handler to the getGraphAccessTokenButton button click event.
    • メソッドは、作業ウィンドウの下側に Microsoft Graph から返されたデータ (またはエラー メッセージ) を表示するものです。showResultA showResult method that will display data returned from Microsoft Graph (or an error message) at the bottom of the task pane.
    • メソッドは、エンド ユーザーを対象としていないエラーをコンソールにログ出力するものです。logErrorsA logErrors method that will log to console errors that are not intended for the end user.
  2. Office.initialize への割り当ての下に、次のコードを追加します。このコードについては、次の点に注意してください。Below the assignment to Office.initialize, add the code below. Note the following about this code:

    • アドインのエラー処理により、アクセス トークンの取得が別のオプションのセットを使用して自動的に再試行されることがあります。The error-handling in the add-in will sometimes automatically attempt a second time to get an access token, using a different set of options. カウンター変数 timesGetOneDriveFilesHasRun とフラグ変数 triedWithoutForceConsent および timesMSGraphErrorReceived を使用して、失敗するトークン取得の繰り返しからユーザーが抜け出せるようにします。The counter variable timesGetOneDriveFilesHasRun, and the flag variables triedWithoutForceConsent and timesMSGraphErrorReceived are used to ensure that the user isn't cycled repeatedly through failed attempts to get a token.
    • この後の手順では getDataWithToken メソッドを作成しますが、そのメソッドで forceConsent というオプションが false に設定される点に注意してください。詳細については、次の手順で説明します。You create the getDataWithToken method in the next step, but note that it sets an option called forceConsent to false. More about that in the next step.
    var timesGetOneDriveFilesHasRun = 0;
    var triedWithoutForceConsent = false;
    var timesMSGraphErrorReceived = false;
    function getOneDriveFiles() {
        triedWithoutForceConsent = true;
        getDataWithToken({ forceConsent: false });
  3. メソッドの下に、次のコードを追加します。このコードについては、次の点に注意してください。getOneDriveFilesBelow the getOneDriveFiles method, add the code below. Note the following about this code:

    • getAccessTokenAsync は Office.js の新しい API です。これにより、アドインは Office ホスト アプリケーション (Excel、PowerPoint、Word など) に、アドインへのアクセス トークン (Office にサインインしているユーザーのトークン) を要求できるようになります。The is the new API in Office.js that enables an add-in to ask the Office host application (Excel, PowerPoint, Word, etc.) for an access token to the add-in (for the user signed into Office). その Office ホスト アプリケーションが、Azure AD 2.0 エンドポイントにこのトークンを要求します。The Office host application, in turn, asks the Azure AD 2.0 endpoint for the token. アドインの登録時に、アドインに対する Office ホストを事前認証しているため、Azure AD はそのトークンを送信します。Since you preauthorized the Office host to your add-in when you registered it, Azure AD will send the token.
    • Office にサインインしているユーザーがいない場合、Office ホストはユーザーにサインインを求めるダイアログを表示します。If no user is signed into Office, the Office host will prompt the user to sign in.
    • オプションのパラメーター forceConsentfalse に設定すると、ユーザーがアドインを使用するたびに、Office ホストにアドインへのアクセス権を付与するための同意を求めるダイアログが表示されなくなります。The options parameter sets forceConsent to false, so the user will not be prompted to consent to giving the Office host access to your add-in every time she or he uses the add-in. ユーザーが初めてアドインを実行すると、getAccessTokenAsync の呼び出しは失敗しますが、この後の手順で追加するエラー処理ロジックにより、forceConsent オプションを true に設定した再呼び出しが自動的に実行され、ユーザーに同意を求めるダイアログが表示されます。ただし、これは初回時のみ実行されます。The first time the user runs the add-in, the call of getAccessTokenAsync will fail, but error-handling logic that you add in a later step will automatically re-call with the forceConsent option set to true and the user will be prompted to consent, but only that first time.
    • メソッドは、この後の手順で作成します。handleClientSideErrorsYou will create the handleClientSideErrors method in a later step.

      function getDataWithToken(options) {
        function (result) {
            if (result.status === "succeeded") {
                TODO1: Use the access token to get Microsoft Graph data.
            else {
  4. TODO1 を次に示す行に置き換えます。getData メソッドとサーバー側の "/api/values" ルートは、この後の手順で作成します。エンドポイントには、相対 URL を使用します。これは、その URL がアドインと同じドメインでホストされている必要があるためです。Replace the TODO1 with the following lines. You create the getData method and the server-side “/api/values” route in later steps. A relative URL is used for the endpoint because it must be hosted on the same domain as your add-in.

    accessToken = result.value;
    getData("/api/values", accessToken);
  5. メソッドの下に、以下を追加します。このコードについては、次の点に注意してください。getOneDriveFilesBelow the getOneDriveFiles method, add the following. About this code, note:

    • このメソッドは、特定の Web API エンドポイントを呼び出して、Office ホスト アプリケーションがアドインへのアクセスに使用したものと同じアクセス トークンを渡します。サーバー側では、このアクセス トークンが Microsoft Graph へのアクセス トークンを取得するための「代理 (on-behalf-of)」フローで使用されます。This method calls a specified Web API endpoint and passes it the same access token that the Office host application used to get access to your add-in. On the server-side, this access token will be used in the “on behalf of” flow to obtain an access token to Microsoft Graph.
    • メソッドは、この後の手順で作成します。handleServerSideErrorsYou will create the handleServerSideErrors method in a later step.

      function getData(relativeUrl, accessToken) {
            url: relativeUrl,
            headers: { "Authorization": "Bearer " + accessToken },
            type: "GET"
        .done(function (result) {
        .fail(function (result) {

エラー処理のメソッドを作成するCreate the error-handling methods

  1. メソッドの下に、次のメソッドを追加します。getDataBelow the getData method, add the following method. このメソッドは、Office ホストがアドインの Web サービスへのアクセス トークンを取得できないときに、アドインのクライアントでエラーを処理します。This method will handle errors in the add-in's client when the Office host is unable to obtain an access token to the add-in's web service. こうしたエラーはエラー コードで報告されるため、このメソッドでは switch ステートメントを使用してエラーを識別します。These errors are reported with an error code, so the method uses a switch statement to distinguish them.

    function handleClientSideErrors(result) {
        switch (result.error.code) {
            // TODO2: Handle the case where user is not logged in, or the user cancelled, without responding, a
            //        prompt to provide a 2nd authentication factor. 
            // TODO3: Handle the case where the user's sign-in or consent was aborted.
            // TODO4: Handle the case where the user is logged in with an account that is neither work or school, 
            //        nor Micrososoft Account.
            // TODO5: Handle an unspecified error from the Office host.
            // TODO6: Handle the case where the Office host cannot get an access token to the add-ins 
            //        web service/application.
            // TODO7: Handle the case where the user tiggered an operation that calls `getAccessTokenAsync` 
            //        before a previous call of it completed.
            // TODO8: Handle the case where the add-in does not support forcing consent.
            // TODO9: Log all other client errors.
  2. を次のコードに置き換えます。TODO2Replace TODO2 with the following code. エラー 13001 は、ユーザーがログインしていない場合、または 2 番目の認証要素の指定を求めるダイアログに応答しないでキャンセルした場合に発生します。Error 13001 occurs when the user is not logged in, or the user cancelled, without responding, a prompt to provide a 2nd authentication factor. どちらの場合も、このコードでは getDataWithToken メソッドを再実行して、サインインを求めるダイアログの表示を強制するようにオプションを設定します。In either case, the code re-runs the getDataWithToken method and sets an option to force a sign-in prompt.

    case 13001:
        getDataWithToken({ forceAddAccount: true });
  3. を次のコードに置き換えます。TODO3Replace TODO3 with the following code. エラー 13002 は、ユーザーのサインインまたは同意が中断された場合に発生します。Error 13002 occurs when user's sign-in or consent was aborted. ユーザーに対して 1 回だけ再試行を求めます。Ask the user to try again but no more than once again.

    case 13002:
        if (timesGetOneDriveFilesHasRun < 2) {
            showResult(['Your sign-in or consent was aborted before completion. Please try that operation again.']);
        } else {
  4. を次のコードに置き換えます。TODO4Replace TODO4 with the following code. エラー 13003 は、ユーザーが職場または学校アカウントと、Micrososoft アカウントのどちらでもないアカウントでログインしている場合に発生します。Error 13003 occurs when user is logged in with an account that is neither work or school, nor Micrososoft Account. ユーザーに対して、サインアウトしてからサポートされているアカウントの種類で再度サインインするように求めます。Ask the user to sign-out and then in again with a supported account type.

    case 13003: 
        showResult(['Please sign out of Office and sign in again with a work or school account, or Microsoft Account. Other kinds of accounts, like corporate domain accounts do not work.']);


    エラー 13004 と 13005 は、開発時にのみ発生するため、このメソッドでは処理しません。Errors 13004 and 13005 are not handled in this method because they should only occur in development. これらは、ランタイム コードで修正できるものではなく、エンド ユーザーに報告しても意味がありません。They cannot be fixed by runtime code and there would be no point in reporting them to an end user.

  5. を次のコードと置き換えます。エラー 13006 は、Office ホストで未指定のエラーがある場合に発生します。ホストが不安定な状態にあることを示している可能性があります。ユーザーに Office の再起動を求めます。TODO5Replace TODO5 with the following code. Error 13006 occurs when there has been an unspecified error in the Office host that may indicate that the host is in an unstable state. Ask the user to restart Office.

    case 13006:
        showResult(['Please save your work, sign out of Office, close all Office applications, and restart this Office application.']);
  6. を次のコードに置き換えます。TODO6Replace TODO6 with the following code. エラー 13007 は、Office ホストの AAD との相互作用に問題があり、ホストがアドイン Web サービス/アプリケーションへのアクセス トークンを取得できない場合に発生します。Error 13007 occurs when something has gone wrong with the Office host's interaction with AAD so the host cannot get an access token to the add-ins web service/application. ネットワークに一時的な問題が発生している可能性があります。This may be a temporary network issue. しばらく待ってから再試行するようにユーザーに求めます。Ask the user to try again later.

    case 13007:
        showResult(['That operation cannot be done at this time. Please try again later.']);
  7. TODO7 を次のコードと置き換えます。エラー 13008 は、前回の getAccessTokenAsync の呼び出しが完了する前に、それを呼び出す操作をユーザーがトリガーしたときに発生します。Replace TODO7 with the following code. Error 13008 occurs when the user tiggered an operation that calls getAccessTokenAsync before a previous call of it completed.

    case 13008:
        showResult(['Please try that operation again after the current operation has finished.']);
  8. を次のコードに置き換えます。TODO8Replace TODO8 with the following code. エラー 13009 は、アドインが強制的な同意をサポートしていないときに、forceConsent オプションを true に設定して getAccessTokenAsync を呼び出した場合に発生します。Error 13009 occurs when the add-in does not support forcing consent, but getAccessTokenAsync was called with the forceConsent option set to true. 通常、この場合は、コードによって同意オプションを false に設定して自動的に getAccessTokenAsync を再実行する必要があります。In the usual case when this happens the code should automatically re-run getAccessTokenAsync with the consent option set to false. ただし、forceConsenttrue に設定してメソッドを呼び出すこと自体が、そのオプションを false に設定したメソッドの呼び出しで発生したエラーに対する自動的な応答の場合もあります。However, in some cases, calling the method with forceConsent set to true was itself an automatic response to an error in a call to the method with the option set to false. その場合は、コードで再試行するのではなく、ユーザーにサインアウトしてから再度サインインするように通知する必要があります。In that case, the code should not try again, but instead it should advise the user to sign out and sign in again.

    case 13009:
        if (triedWithoutForceConsent) {
            showResult(['Please sign out of Office and sign in again with a work or school account, or Microsoft Account.']);
        } else {
            getDataWithToken({ forceConsent: false });
  9. を次のコードに置き換えます。TODO9Replace TODO9 with the following code.

  10. メソッドの下に、次のメソッドを追加します。このメソッドは、代理 (on-behalf-of) フローの実行時または Microsoft Graph からのデータの取得時の問題により、アドインの Web サービスで発生したエラーを処理します。handleClientSideErrorsBelow the handleClientSideErrors method, add the following method. This method will handle errors in the add-in's web service when something goes wrong in executing the on-behalf-of flow or in getting data from Microsoft Graph.

    function handleServerSideErrors(result) {
        // TODO10: Handle the case where AAD asks for an additional form of authentication.
        // TODO11: Handle the case where consent has not been granted, or has been revoked.
        // TODO12: Handle the case where an invalid scope (permission) was used in the on-behalf-of flow
        // TODO13: Handle the case where the token that the add-in's client-side sends to it's 
        //         server-side is not valid because it is missing `access_as_user` scope (permission).
        // TODO14: Handle the case where the token sent to Microsoft Graph in the request for 
        //         data is expired or invalid.
        // TODO15: Log all other server errors.
  11. TODO10 を次のコードに置き換えます。このコードの注意点は次のとおりです。Replace TODO10 with the following code. Note about this code:

    • ユーザーがパスワードだけで Office にサインオンできる場合でも、Microsoft Graph のいくつかのターゲット (たとえば、OneDrive) にアクセスするために、追加の認証要素を提供するようにユーザーに要求する、Azure Active Directory の構成があります。その場合、AAD は Claims プロパティを含むエラー 50076 で応答を送信します。There are configurations of Azure Active Directory in which the user is required to provide additional authentication factor(s) to access some Microsoft Graph targets (e.g., OneDrive), even if the user can sign on to Office with just a password. In that case, AAD will send a response, with error 50076, that has a Claims property.
    • Office ホストは、authChallenge オプションとして Claims 値を使用して新しいトークンを取得します。The Office host should get a new token with the Claims value as the authChallenge option. これにより、認証のすべての必要なフォームをユーザーに表示するように AAD に指示します。This tells AAD to prompt the user for all required forms of authentication.

      if (result.responseJSON.error.innerError
            && result.responseJSON.error.innerError.error_codes
            && result.responseJSON.error.innerError.error_codes[0] === 50076){
        getDataWithToken({ authChallenge: result.responseJSON.error.innerError.claims });
  12. を次のコードに置き換えます (前の手順で追加したコードの最後にある右波かっこのすぐ下)。このコードの注意点は次のとおりです。TODO11Replace TODO11 with the following code just below the last closing brace of the code you added in the previous step. Note about this code:

    • エラー 65001 は、1 つ以上のアクセス許可について Microsoft Graph にアクセスするための同意が与えられていない (または取り消されている) ことを意味します。Error 65001 means that consent to access Microsoft Graph was not granted (or was revoked) for one or more permissions.
    • アドインでは、forceConsent オプションを true に設定して新しいトークンを取得する必要があります。The add-in should get a new token with the forceConsent option set to true.

      else if (result.responseJSON.error.innerError
            && result.responseJSON.error.innerError.error_codes
            && result.responseJSON.error.innerError.error_codes[0] === 65001){
        showResult(['Please grant consent to this add-in to access your Microsoft Graph data.']);        
        // getDataWithToken({ forceConsent: true });
  13. を次のコードに置き換えます (前の手順で追加したコードの最後にある右波かっこのすぐ下)。このコードの注意点は次のとおりです。TODO12Replace TODO12 with the following code just below the last closing brace of the code you added in the previous step. Note about this code:

    • エラー 70011 は、無効なスコープ (アクセス許可) が要求されたことを示します。Error 70011 means that an invalid scope (permission) has been requested. アドインでは、エラーを報告する必要があります。The add-in should report the error.
    • コードでは、その他のエラーを AAD エラー番号と共に記録します。The code logs any other error with an AAD error number.

      else if (result.responseJSON.error.innerError
            && result.responseJSON.error.innerError.error_codes
            && result.responseJSON.error.innerError.error_codes[0] === 70011){
        showResult(['The add-in is asking for a type of permission that is not recognized.']);
  14. を次のコードに置き換えます (前の手順で追加したコードの最後にある右波かっこのすぐ下)。このコードの注意点は次のとおりです。TODO13Replace TODO13 with the following code just below the last closing brace of the code you added in the previous step. Note about this code:

    • この後の手順で作成するサーバー側のコードでは、アドインのクライアントが AAD に送信して代理 (on-behalf-of) フローで使用されるアクセス トークンに access_as_user スコープ (アクセス許可) が含まれていない場合に、末尾が ... expected access_as_user のメッセージを送信します。Server-side code that you create in a later step will send the message that ends with ... expected access_as_user if the access_as_user scope (permission) is not in the access token that the add-in's client sends to AAD to be used in the on-behalf-of flow.
    • アドインでは、エラーを報告する必要があります。The add-in should report the error.

      else if (result.responseJSON.error.name
            && result.responseJSON.error.name.indexOf('expected access_as_user') !== -1){
        showResult(['Microsoft Office does not have permission to get Microsoft Graph data on behalf of the current user.']);
  15. を次のコードに置き換えます (前の手順で追加したコードの最後にある右波かっこのすぐ下)。このコードの注意点は次のとおりです。TODO14Replace TODO14 with the following code just below the last closing brace of the code you added in the previous step. Note about this code:

    • 有効期限切れのトークンや無効なトークンが Microsoft Graph に送信される可能性はほとんどありませんが、そのような事態が発生した場合は、この後の手順で作成するサーバー側のコードは、文字列 Microsoft Graph error で終了します。It is unlikely that an expired or invalid token will be sent to Microsoft Graph; but if it does happen, the server-side code that you will create in a later step will end with the string Microsoft Graph error.
    • この場合、アドインは timesGetOneDriveFilesHasRun カウンター変数と timesGetOneDriveFilesHasRun フラグ変数をリセットしてから、ボタン ハンドラー メソッドを再呼び出しすることで、認証プロセス全体を最初から開始する必要があります。In this case, the add-in should start the entire authentication process over by resetting the timesGetOneDriveFilesHasRun counter and timesGetOneDriveFilesHasRun flag variables, and then re-calling the button handler method. ただし、これは 1 回のみ実行する必要があります。But it should do this only once. この事態が再度発生した場合は、単にエラーを記録するようにします。If it happens again, it should just log the error.
    • コードでは、この事態が連続して 2 回発生した場合にエラーを記録します。The code logs the error if it happens twice in succession.

      else if (result.responseJSON.error.name
            && result.responseJSON.error.name.indexOf('Microsoft Graph error') !== -1) {
        if (!timesMSGraphErrorReceived) {
            timesMSGraphErrorReceived = true;
            timesGetOneDriveFilesHasRun = 0;
            triedWithoutForceConsent = false;
        } else {
  16. を次のコードに置き換えます (前の手順で追加したコードの最後にある右波かっこのすぐ下)。TODO15Replace TODO15 with the following code just below the last closing brace of the code you added in the previous step.

    else {

サーバー側のコードを作成するCode the server side

変更の必要があるサーバー側のファイルは 2 つあります。There are two server-side files that need to be modified.

  • src\auth.js では、承認のヘルパー関数を提供します。これには、各種の承認フローで使用される汎用のメンバーが既に含まれています。これには、「代理」フローを実装するための関数を追加する必要があります。The src\auth.js provides authorization helper functions. It already has generic members that are used in a variety of authorization flows. We need to add functions to it that implement the "on behalf of" flow.
  • src\server.js ファイルには、サーバーと express ミドルウェアを実行するために必要な基本的なメンバーが含まれています。これには、ホーム ページと Microsoft Graph データを取得するための Web API を提供する関数を追加する必要があります。The src\server.js file has the basic members need to run a server and express middleware. We need to add functions to it that serve the home page and a Web API for obtaining Microsoft Graph data.

トークンを交換するためのメソッドを作成するCreate a method to exchange tokens

  1. \src\auth.ts ファイルを開きます。AuthModule クラスに、次に示すメソッドを追加します。このコードについては、次の点に注意してください。Open the \src\auth.ts file. Add the method below to the AuthModule class. Note the following about this code:

    • パラメーターは、アプリケーションへのアクセス トークンです。「代理 (on-behalf-of)」フローでは、これはリソースへのアクセス トークンの AAD と交換されます。jwtThe jwt parameter is the access token to the application. In the "on behalf of" flow, it is exchanged with AAD for an access token to the resource.
    • scopes パラメーターには既定の値がありますが、このサンプルではコード呼び出しによってオーバーライドしています。The scopes parameter has a default value, but in this sample it will be overridden by the calling code.
    • resource パラメーターは省略可能です。STS が AAD V 2.0 エンドポイントの場合は使用しないでください。V 2.0 エンドポイントは scopes から resource を推測します。resource が HTTP 要求で送信されるとエラーを返します。The resource parameter is optional. It should not be used when the STS is the AAD V 2.0 endpoint. The V 2.0 endpoint infers the resource from the scopes and it returns an error if a resource is sent in the HTTP Request.
    • ブロック内で例外をスローしても、即時の "500 Internal Server Error" がクライアントに送信されることはありませんcatchThrowing an exception in the catch block will not cause an immediate "500 Internal Server Error" to be sent to the client. server.js ファイルでコードを呼び出すことで、この例外をキャッチしてから、その例外をクライアントに送信するエラー メッセージに変換します。Calling code in the server.js file will catch this exception and turn it into an error message that is sent to the client.

      private async exchangeForToken(jwt: string, scopes: string[] = ['openid'], resource?: string) {
          try {
              // TODO3: Construct the parameters that will be sent in the body of the 
              //        HTTP Request to the STS that starts the "on behalf of" flow.
              // TODO4: Send the request to the STS.
              // TODO5: Catch errors from the STS and relay them to the client.
              // TODO6: Process the response and persist the access token to resource.
          catch (exception) {
              throw new UnauthorizedError('Unable to obtain an access token to the resource' 
                                          + JSON.stringify(exception), 
  2. TODO3 を次のコードに置き換えます。このコードの注意点は次のとおりです。Replace TODO3 with the following code. About this code, note:

    • 「代理」ワークフローをサポートする STS は、HTTP 要求の本文に特定のプロパティ/値ペアが含まれていることを期待します。このコードは、要求の本文になるオブジェクトを構築します。An STS that supports the "on behalf of" flow expects certain property/value pairs in the body of the HTTP request. This code constructs an object that will become the body of the request.
    • resource プロパティは、リソースがメソッドに渡された場合にのみ本文に追加されます。A resource property is added to the body if, and only if, a resource was passed to the method.

      const v2Params = {
              client_id: this.clientId,
              client_secret: this.clientSecret,
              grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
              assertion: jwt,
              requested_token_use: 'on_behalf_of',
              scope: scopes.join(' ')
          let finalParams = {};
          if (resource) {
              // In JavaScript we could just add the resource property to the v2Params
              // object, but that won't compile in TypeScript.
              let v1Params  = { resource: resource };  
              for(var key in v2Params) { v1Params[key] = v2Params[key]; }
              finalParams = v1Params;
          } else {
              finalParams = v2Params;
  3. を次に示すコードに置き換えます。このコードでは、HTTP 要求を STS のトークン エンドポイントに送信します。TODO4Replace TODO4 with the following code which sends the HTTP request to the token endpoint of the STS.

    const res = await fetch(`${this.stsDomain}/${this.tenant}/${this.tokenURLsegment}`, {
        method: 'POST',
        body: form(finalParams),
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/x-www-form-urlencoded'
  4. を次のコードに置き換えます。TODO5Replace TODO5 with the following code. 例外をスローしても、即時の "500 Internal Server Error" がクライアントに送信されない点に注意してください。Note that throwing an exception will not cause an immediate "500 Internal Server Error" to be sent to the client. server.js ファイルでコードを呼び出すことで、この例外をキャッチしてから、その例外をクライアントに送信するエラー メッセージに変換します。Calling code in the server.js file will catch this exception and turn it into an error message that is sent to the client.

     if (res.status !== 200) {
        const exception = await res.json();
        throw exception;                
  5. を次に示すコードに置き換えます。このコードはリソースへのアクセス トークンを永続化して、有効期限になると、そのアクセス トークンを返します。コードを呼び出すことで、期限切れになっていないリソースへのアクセス トークンが再使用されるため、STS への不要な呼び出しを回避できます。この動作のしくみは、次のセクションで説明します。TODO6Replace TODO6 with the following code. Note that the code persists the access token to the resource, and it's expiration time, in addition to returning it. Calling code can avoid unnecessary calls to the STS by reusing an unexpired access token to the resource. You'll see how to do that in the next section.

    const json = await res.json();
    const resourceToken = json['access_token'];
    ServerStorage.persist('ResourceToken', resourceToken);
    const expiresIn = json['expires_in'];  // seconds until token expires.
    const resourceTokenExpiresAt = moment().add(expiresIn, 'seconds');
    ServerStorage.persist('ResourceTokenExpiresAt', resourceTokenExpiresAt);
    return resourceToken; 
  6. ファイルを閉じないで保存します。Save the file, but don't close it.

「代理」ワークフローを使用してリソースにアクセスするメソッドを作成するCreate a method to get access to the resource using the "on behalf of" flow

  1. 引き続き src/auth.ts で、次に示すメソッドを AuthModule クラスに追加します。このコードについては、以下に注意してください。Still in src/auth.ts, add the method below to the AuthModule class. Note the following about this code:

    • メソッドへのパラメーターに関する上記のコメントは、このメソッドのパラメーターにも当てはまります。exchangeForTokenThe comments above about the parameters to the the exchangeForToken method apply to the parameters of this method as well.
    • このメソッドでは、最初にリソースへの有効期限が切れていない (次の 1 分まで有効期限が続く) アクセス トークンについて永続ストレージをチェックします。これは、直前のセクションで作成した exchangeForToken メソッドを呼び出します (そのメソッドが必要になる場合)。The method first checks the persistent storage for an access token to the resource that has not expired and is not going to expire in the next minute. It calls the exchangeForToken method you created in the last section only if it needs to.

      async acquireTokenOnBehalfOf(jwt: string, scopes: string[] = ['openid'], resource?: string) {
        const resourceTokenExpirationTime = ServerStorage.retrieve('ResourceTokenExpiresAt');
        if (moment().add(1, 'minute').diff(resourceTokenExpirationTime) < 1 ) {
            return ServerStorage.retrieve('ResourceToken');
        } else if (resource) {
            return this.exchangeForToken(jwt, scopes, resource);
        } else {
            return this.exchangeForToken(jwt, scopes);
  2. ファイルを保存して閉じます。Save and close the file.

アドインのホーム ページとデータを提供するエンドポイントを作成するCreate the endpoints that will serve the add-in's home page and data

  1. src\server.ts ファイルを開きます。Open the src\server.ts file.

  2. 次に示すメソッドをファイルの末尾に追加します。このメソッドにより、アドインのホーム ページを提供します。アドイン マニフェストで、ホーム ページの URL を指定します。Add the following method to the bottom of the file. This method will serve the add-in's home page. The add-in manifest specifies the home page URL.

    app.get('/index.html', handler(async (req, res) => {
        return res.sendfile('index.html');
  3. ファイルの末尾に次のメソッドを追加します。このメソッドにより、onedriveitems API に対する要求を処理します。Add the following method to bottom of the file. This method will handle any requests for the onedriveitems API.

    app.get('/api/onedriveitems', handler(async (req, res) => {
        // TODO7: Initialize the AuthModule object and validate the access token 
        //        that the client-side received from the Office host.
        // TODO8: Get a token to Microsoft Graph from either persistent storage 
        //        or the "on behalf of" flow.
        // TODO9: Use the token to get data from Microsoft Graph.
        // TODO10: Relay any errors from Microsoft Graph to the client.
        // TODO11: Send to the client only the data that it actually needs.
  4. を次に示すコードに置き換えます。このコードでは、Office ホスト アプリケーションから受け取ったアクセス トークンを検証します。verifyJWT メソッドは、src\auth.ts ファイルで定義されています。これは、常に対象ユーザーと発行者を検証します。省略可能なパラメーターを使用して、アクセス トークンのスコープが access_as_user であることを検証する必要もあることを指定します。これは、「代理 (on-behalf-of)」フローによって Microsoft Graph へのアクセストークンを取得するために、ユーザーと Office ホストが必要とする唯一のアクセス許可です。TODO7Replace TODO7 with the following code which validates the access token received from the Office host application. The verifyJWT method is defined in the src\auth.ts file. It always validates the audience and the issuer. We use the optional parameter to specify that we also want it to verify that the scope in the access token is access_as_user. This is the only permisison to the add-in that the user and the Office host need in order to get an access token to Microsoft Graph by means of the "on behalf" flow.

    await auth.initialize();
    const { jwt } = auth.verifyJWT(req, { scp: 'access_as_user' }); 


    注: access_as_user スコープだけを使用して、Office アドインの代理フローを処理する API を承認する必要があります。サービス内の他の API には、独自のスコープ要件が必要です。Note: You should only use the access_as_user scope to authorize the API that handles the on-behalf-of flow for Office add-ins. Other APIs in your service should have their own scope requirements. これにより、Office が取得するトークンでアクセスできる対象が制限されます。This limits what can be accessed with the tokens that Office acquires.

  5. を次のコードに置き換えます。このコードについては、次の点に注意してください。TODO8Replace TODO8 with the following code. Note the following about this code:

    • の呼び出しには、resource パラメーターは含まれません。これは、resource プロパティをサポートしていない AAD V2.0 エンドポイントで AuthModule オブジェクト (auth) を作成したためです。acquireTokenOnBehalfOfThe call to acquireTokenOnBehalfOf does not include a resource parameter because we constructed the AuthModule object (auth) with the AAD V2.0 endpoint which does not support a resource property.
    • この呼び出しの 2 番目のパラメーターでは、OneDrive 上のユーザーのファイルとフォルダーのリストを取得するために、アドインが必要とするアクセス許可を指定します。The second parameter of the call specifies the permissions the add-in will need to get a list of the user's files and folders on OneDrive. (profile アクセス許可は要求されません。これは、このアクセス許可が、Microsoft Graph へのアクセス トークン用のトークンでやり取りしているときではなく、Office ホストがアドインへのアクセス トークンを取得するときにだけ必要であるためです。)(The profile permission is not requested because it is only needed when the Office host gets the access token to your add-in, not when you are trading in that token for an access token to Microsoft Graph.)

      const graphToken = await auth.acquireTokenOnBehalfOf(jwt, ['Files.Read.All']);
  6. TODO9 を次のコードに置き換えます。このコードについては、次の点に注意してください。Replace TODO9 with the following line. Note the following about this code:

    • MSGraphHelper クラスは、src\msgraph-helper.ts で定義されています。The MSGraphHelper class is defined in src\msgraph-helper.ts.
    • 返す必要があるデータが最小になるように、name プロパティと最初の 3 つのアイテムのみが必要なことを指定しています。We minimize the data that must be returned by specifying that we only want the name property and only the first 3 items.

      const graphData = await MSGraphHelper.getGraphData(graphToken, "/me/drive/root/children", "?$select=name&$top=3");

  7. を次のコードに置き換えます。TODO10Replace TODO10 with the following code. このコードでは、Microsoft Graph からの "401 Unauthorized" エラーを処理します。このエラーは、期限切れのトークンまたは無効なトークンを表している可能性があります。Note that this code handles '401 Unauthorized" errors from Microsoft Graph which would indicate an expired or invalid token. この事態は、トークンの永続化ロジックによって防止されているため、発生する可能性はほとんどありませんIt is very unlikely that this would ever happen since the token persisting logic should prevent it. (前述のセクション「「代理 (on-behalf-of) 」ワークフローを使用してリソースにアクセスするメソッドを作成する」を参照してください)。この事態が発生した場合、このコードではエラー名に "Microsoft Graph error" を使用してクライアントにエラーを中継します(See the section Create a method to get access to the resource using the "on behalf of" flow above.) If it does happen, this code will relay the error to the client with "Microsoft Graph error" in the error name. (前述の手順で program.js ファイルに作成した handleClientSideErrors メソッドを参照してください)。この後手順で ODataHelper.js ファイルに追加するコードは、Microsoft Graph からのエラーの処理に役立ちます。(See the handleClientSideErrors method that you created in the program.js file in an earlier step.) Code that you add to the ODataHelper.js file in a later step helps process errors from Microsoft Graph.

    if (graphData.code) {
        if (graphData.code === 401) {
            throw new UnauthorizedError('Microsoft Graph error', graphData);
  8. TODO11 を次に示すコードに置き換えます。Microsoft Graph は、name プロパティのみを要求した場合でも、アイテムごとに、いくつかの OData メタデータと 1 つの eTag プロパティを返す点に注意してください。このコードでは、アイテムの名前のみをクライアントに送信します。Replace TODO11 with the following code. Note that Microsoft Graph returns some OData metadata and an eTag property for every item, even if name is the only property requested. The code sends only the item names to the client.

    const itemNames: string[] = [];
    const oneDriveItems: string[] = graphData['value'];
    for (let item of oneDriveItems){
    return res.json(itemNames);
  9. ファイルを保存して閉じます。Save and close the file.

ODataHelper に応答の処理を追加するAdd response handling to the ODataHelper

  1. ファイル src\odata-helper.ts を開きます。Open the file src\odata-helper.ts. このファイルは、ほとんど完成しています。The file is almost complete. 要求の「終了」イベントを処理するコールバックの本文が欠落しています。What's missing is the body of the callback to the handler for the request "end" event. を次のコードに置き換えます。TODOReplace the TODO with the following code. このコードの注意点は次のとおりです。About this code note:

    • OData エンドポイントからの応答は、エラーである可能性があります。たとえば、エンドポイントがアクセス トークンを必要としていて、そのトークンが無効または有効期限切れの場合は 401 になります。The response from the OData endpoint might be an error, say a 401 if the endpoint requires an access token and it was invalid or expired. ただし、エラー メッセージは https.get の呼び出しでのエラーではなくメッセージであるため、https.get の最後の行 on('error', reject) はトリガーされません。But an error message is still a message, not an error in the call of https.get, so the on('error', reject) line at the end of https.get isn't triggered. そのため、コードでは、成功 (200) とエラー メッセージを区別して、要求された OData またはエラー情報のどちらかを含む JSON オブジェクトを呼び出し元に送信します。So, the code distinguishes success (200) messages from error messages and sends a JSON object to the caller with either the requested OData or error information.

      var error;
      if (response.statusCode === 200) {
        // TODO1: Return the data to the caller and resolve the Promise.
      } else {
       // TODO2: Return an error object to the caller and resolve the Promise.
  2. TODO1 を次のコードと置き換えます。このコードでは、データが JSON として返されることを前提としています。Replace TODO1 with the following code. Note that the code assumes the data is returned as JSON.

    let parsedBody = JSON.parse(body);
  3. TODO2 を次のコードに置き換えます。このコードの注意点は次のとおりです。Replace TODO2 with the following code. Note about this code:

    • OData ソースからのエラー応答には、常に statusCode が含まれています。また、通常は statusMessage が含まれています。An error response from an OData source will always have a statusCode and usually a statusMessage. また、一部の OData ソースは、詳細な情報 (内部のコードやメッセージ、より具体的なコードやメッセージなど) を含む error プロパティも本文に追加します。Some OData sources also add an error property to the body with further information, such as an inner, or more specific, code and message.
    • Promise オブジェクトは解決されます。拒否されません。The Promise object is resolved, not rejected. https.get は、Web サービスがサーバー間の OData エンドポイントを呼び出すときに実行されます。The https.get runs when a web service calls an OData endpoint server-to-server. ただし、その呼び出しは、クライアントから Web サービスの Web API への呼び出しのコンテキストで行われます。But that call comes in the context of a call from a client to a web API in the web service. クライアントから Web サービスへの「外部」の要求は、「内部」の要求が拒否されると完了できなくなります。The "outer" request from the client to the web service never completes if this "inner" request is rejected. さらに、http.get の呼び出し元が OData エンドポイントからクライアントにエラーを中継する必要がある場合は、カスタムの Error オブジェクトを含む要求も解決する必要があります。Also, resolving the request with the custom Error object is required if the caller of http.get needs to relay errors from the OData endpoint to the client.
    error = new Error();
    error.code = response.statusCode;
    error.message = response.statusMessage;
    // The error body sometimes includes an empty space
    // before the first character, remove it or it causes an error.
    body = body.trim();
    error.bodyCode = JSON.parse(body).error.code;
    error.bodyMessage = JSON.parse(body).error.message;
  4. ファイルを保存して閉じます。Save and close the file.

アドインを展開するDeploy the add-in

次に、Office がアドインを検索する場所を認識できるようにする必要があります。Now you need to let Office know where to find the add-in.

  1. ネットワーク共有を作成するか、フォルダーをネットワークに共有しますCreate a network share, or share a folder to the network.

  2. プロジェクトのルートから、Office-Add-in-NodeJS-SSO.xml マニフェスト ファイルのコピーを共有フォルダーに配置します。Place a copy of the Office-Add-in-NodeJS-SSO.xml manifest file, from the root of the project, into the shared folder.

  3. PowerPoint を起動して、ドキュメントを開きます。Launch PowerPoint and open a document.

  4. [ファイル] タブを選択して、[オプション] を選択します。Choose the File tab, and then choose Options.

  5. [セキュリティ センター] を選択し、[セキュリティ センターの設定] ボタンを選択します。Choose Trust Center, and then choose the Trust Center Settings button.

  6. [信頼されているアドイン カタログ] を選択します。Choose Trusted Add-ins Catalogs.

  7. [カタログの URL] フィールドに、Office-Add-in-NodeJS-SSO.xml があるフォルダー共有へのネットワーク パスを入力して、[カタログの追加] を選択します。In the Catalog Url field, enter the network path to the folder share that contains Office-Add-in-NodeJS-SSO.xml, and then choose Add Catalog.

  8. [メニューに表示する] チェック ボックスをオンにして、[OK] を選択します。Select the Show in Menu check box, and then choose OK.

  9. これらの設定は Microsoft Office を次回起動したときに適用されることを示すメッセージが表示されます。PowerPoint を終了します。A message is displayed to inform you that your settings will be applied the next time you start Microsoft Office. Close PowerPoint.

プロジェクトのビルドと実行Build and run the project

プロジェクトのビルドと実行には 2 つの方法があり、Visual Studio Code を使用しているかどうかによって決まります。どちらの方法でも、プロジェクトをビルドして、コードに変更を加えたときには自動的に再ビルドしてから再実行します。There are two ways to build and run the project depending on whether you are using Visual Studio Code. For both ways, the project builds and automatically rebuilds and reruns when you make changes to the code.

  1. Visual Studio Code を使用していない場合:If you are not using Visual Studio Code:

    1. ノード ターミナルを開いて、プロジェクトのルート フォルダーに移動します。Open a node terminal and navigate to the root folder of the project.
    2. ターミナルで、「npm run build」と入力します。In the terminal, enter npm run build.
    3. 2 番目のノード ターミナルを開いて、プロジェクトのルート フォルダーに移動します。Open a second node terminal and navigate to the root folder of the project.
    4. ターミナルで、「npm run start」と入力します。In the terminal, enter npm run start.
  2. VS Code を使用している場合:If you are using VS Code:

    1. VS Code でプロジェクトを開きます。Open the project in VS Code.
    2. CTRL + SHIFT + B を押して、プロジェクトをビルドします。Press CTRL-SHIFT-B to build the project.
    3. F5 を押して、デバッグ セッションでプロジェクトを実行します。Press F5 to run the project in a debugging session.

Office ドキュメントにアドインを追加するAdd the add-in to an Office document

  1. PowerPoint を再起動して、プレゼンテーションを開くか作成します。Restart PowerPoint and open or create a presentation.

  2. [開発] タブがリボンに表示されていない場合は、次の手順で有効にします。If the Developer tab is not visible on the ribbon, enable it with the following steps:

    1. *[ファイル]* | *[オプション]* | *[リボンのカスタマイズ]* と移動します。Navigate to File | Options | Customize Ribbon.
    2. *[リボンのカスタマイズ]* ] ページの右上のコントロールの名前のツリーの *[開発]* を有効にするためにチェック ボックスをクリックします。Click the check box to enable Developer in the tree of control names on the right of the Customize Ribbon page.
    3. [OK] をクリックします。Press OK.
  3. PowerPoint の [開発] タブで、[個人用アドイン] を選択します。On the Developer tab in PowerPoint, choose My Add-ins.

  4. [共有フォルダー] タブを選択します。Select the SHARED FOLDER tab.

  5. [SSO NodeJS Sample] を選択して、[OK] を選択します。Choose SSO NodeJS Sample, and then select OK.

  6. [ホーム] リボンに、[SSO NodeJS] という新しいグループが表示され、[アドインの表示] というラベルの付いたボタンとアイコンが含まれています。On the Home ribbon is a new group called SSO NodeJS with a button labeled Show Add-in and an icon.

アドインをテストするTest the add-in

  1. 結果を確認できるように、OneDrive 内にファイルがいくつかあることを確認します。Ensure that you have some files in your OneDrive so that you can verify the results.

  2. [アドインの表示] ボタンをクリックして、アドインを開きます。Click Show Add-in button to open the add-in.

  3. [ようこそ] ページでアドインが開きます。[OneDrive からファイルを取得] ボタンをクリックします。The add-in opens with a Welcome page. Click the Get My Files from OneDrive button.

  4. Office にサインインしている場合は、このボタンの下に OneDrive にあるファイルとフォルダーのリストが表示されます。これは、初回実行時には 15 秒以上かかることがあります。If you are are signed into Office, a list of your files and folders on OneDrive will appear below the button. This may take more than 15 seconds the first time.

  5. Office にサインインしていない場合は、ポップアップが表示され、サインインするように求められます。サインインが完了すると、数秒後にファイルとフォルダーが表示されます。2 回目にボタンをクリックする必要はありません。If you are not signed into Office, a popup will open and prompt you to sign in. After you have completed the sign-in, the list of your files and folders will appear after a few seconds. You do not press the button a second time.


以前に別の ID で Office にサインオンしていて、そのときに開いたいくつかの Office アプリケーションが引き続き開いている場合、Office がその ID を確実に変更するとは限りません (PowerPoint で ID が変更済みのように表示されている場合でも)。If you were previously signed on to Office with a different ID, and some Office applications that were open at the time are still open, Office may not reliably change your ID even if it appears to have done so in PowerPoint. このような場合は、Microsoft Graph への呼び出しが失敗するか、以前の ID からのデータが返される可能性があります。If this happens, the call to Microsoft Graph may fail or data from the previous ID may be returned. これを防止するには、必ず他のすべての Office アプリケーションを閉じてから、[OneDrive からファイルを取得] を押します。To prevent this, be sure to close all other Office applications before you press Get My Files from OneDrive.