シングル サインオンを使用する Node.js Office アドインを作成する
ユーザーは Office にサインインできます。Office Web アドインでは、このサインイン プロセスを利用して、ユーザーに 2 回目のサインインを要求することなく、アドインと Microsoft Graph に対するユーザーの承認を行うことができます。 概要については、「Office アドインで SSO を有効化する」を参照してください。
この記事では、アドインでシングル サインオン (SSO) を有効にするプロセスについて説明します。 作成するサンプル アドインには 2 つの部分があります。Microsoft Excel に読み込まれる作業ウィンドウと、作業ウィンドウの Microsoft Graph への呼び出しを処理する中間層サーバー。 中間層サーバーは、Node.js と Express を使用して構築され、ユーザーの OneDrive フォルダー内の最初の 10 個のファイル名の一覧を返す 1 つの REST API /getuserfilenames
を公開します。 作業ウィンドウでは、 getAccessToken()
メソッドを使用して、中間層サーバーにサインインしているユーザーのアクセス トークンを取得します。 中間層サーバーは、On-Behalf-Of フロー (OBO) を使用して、Microsoft Graph にアクセスできる新しいサーバーのアクセス トークンを交換します。 このパターンを拡張して、任意の Microsoft Graph データにアクセスできます。 作業ウィンドウでは、Microsoft Graph サービスが必要なときに、常に中間層 REST API を呼び出します (アクセス トークンを渡します)。 中間層は、OBO によって取得されたトークンを使用して Microsoft Graph サービスを呼び出し、結果を作業ウィンドウに返します。
この記事では、Node.js と Express を使用するアドインを使用します。 ASP.NET ベースのアドインに関する同様の記事については、「シングル サインオンを使用する ASP.NET Office アドインを作成する」を参照してください。
前提条件
Git バッシュ (またはその他の Git クライアント)
コード エディター - Visual Studio Code をお勧めします
Microsoft 365 サブスクリプションのOneDrive for Businessに保存されている少なくともいくつかのファイルとフォルダー
IdentityAPI 1.3 要件セットをサポートする Microsoft 365 のビルド。 Microsoft 365 開発者プログラムを通じて、開発者サンドボックスを含むMicrosoft 365 E5開発者サブスクリプションの対象となる場合があります。詳細については、「FAQ」を参照してください。 開発者サンドボックスには、この記事の後の手順でアプリの登録に使用できる Microsoft Azure サブスクリプションが含まれています。 必要に応じて、アプリの登録に別の Microsoft Azure サブスクリプションを使用できます。 Microsoft Azure で試用版サブスクリプションを取得します。
スタート プロジェクトをセットアップする
「Office Add-in NodeJS SSO」にあるリポジトリを複製するかダウンロードします。
注:
サンプルには 2 つのバージョンがあります。
- Begin フォルダーはスターター プロジェクトです。 SSO や承認に直接関連しない UI などの側面は、既に完了しています。 この記事で後述する各セクションでは、これを完成させるための手順を順に説明します。
- Complete フォルダーには、この記事のすべてのコーディング手順が完了した同じサンプルが含まれています。 完成したバージョンを使用するには、この記事の手順に従うだけですが、"Begin" を "Complete" に置き換え、「 クライアント側のコーディング 」と「 中間層サーバー側のコーディング 」のセクションをスキップします。
[開始] フォルダーでコマンド プロンプトを開きます。
コンソールで
npm install
を入力して、package.json ファイルに項目化されているすべての依存関係をインストールします。コマンド
npm run install-dev-certs
を実行します。 証明書をインストールするプロンプトに対してはいを選択します。
以降のアプリ登録手順のプレースホルダーには、次の値を使用します。
プレースホルダー | 値 |
---|---|
<add-in-name> |
Office-Add-in-NodeJS-SSO |
<fully-qualified-domain-name> |
localhost:3000 |
Microsoft Graph のアクセス許可 | profile, openid, Files.Read |
アドインを Microsoft ID プラットフォーム に登録する
Web サーバーを表すアプリ登録を Azure で作成する必要があります。 これにより、JavaScript のクライアント コードに対して適切なアクセス トークンを発行できるように、認証のサポートが可能になります。 この登録では、クライアントでの SSO と、Microsoft 認証ライブラリ (MSAL) を使用したフォールバック認証の両方がサポートされます。
Microsoft 365 テナントへの管理者資格情報を使用して、Azure portalにサインインします。 たとえば、「 MyName@contoso.onmicrosoft.com 」のように入力します。
[アプリの登録] を選択します。 アイコンが表示されない場合は、検索バーで "アプリの登録" を検索します。
[アプリの登録] ページが表示されます。
[新規登録] を選択します。
[アプリケーション登録] ページが表示されます。
[アプリケーションを登録] ページで、次のように値を設定します。
-
<add-in-name>
に [名前] を設定します。 - [サポートされているアカウントの種類] を[任意の組織のディレクトリ (任意の Azure AD ディレクトリ - マルチテナント)] と個人用 Microsoft アカウント (Skype、Xbox など) に設定します。
- [ リダイレクト URI] を 設定して、プラットフォーム の単一ページ アプリケーション (SPA) を使用し、URI を
https://<fully-qualified-domain-name>/dialog.html
します。
-
[登録] を選択します。 アプリケーション登録が作成されたことを示すメッセージが表示されます。
アプリケーション (クライアント) ID とディレクトリ (テナント) ID の値をコピーして保存します。 以降の手順では、それらの両方を使用します。
クライアント シークレットを追加する
アプリケーション パスワードと呼ばれることもあります。クライアント シークレットは、証明書の代わりにアプリが ID 自体に使用できる文字列値です。
左側のウィンドウで、[ 証明書 & シークレット] を選択します。 次に、[ クライアント シークレット ] タブで、[ 新しいクライアント シークレット] を選択します。
[ クライアント シークレットの追加] ウィンドウが表示されます。
クライアント シークレットの説明を追加します。
シークレットの有効期限を選択するか、カスタム有効期間を指定します。
- クライアント シークレットの有効期間は、2 年間 (24 か月) 以下に制限されます。 24 か月を超えるカスタム有効期間を指定することはできません。
- Microsoft では、有効期限の値を 12 か月未満に設定することをお勧めします。
[追加] を選択します。 新しいシークレットが作成され、値が一時的に表示されます。
重要
クライアント アプリケーション コードで使用するシークレットの値を記録します。 このウィンドウを離れた後、このシークレット値は 再び表示されることはありません 。
Web API を公開する
左側のウィンドウで、[ API の公開] を選択します。
[ API の公開 ] ウィンドウが表示されます。
[ 設定] を選択して、アプリケーション ID URI を生成します。
アプリケーション ID URI を設定するためのセクションは、生成されたアプリケーション ID URI を
api://<app-id>
フォームに表示します。アプリケーション ID URI を
api://<fully-qualified-domain-name>/<app-id>
に更新します。-
アプリケーション ID URI には、アプリ ID (GUID) が形式
api://<app-id>
で事前に入力されています。 - アプリケーション ID URI 形式は次のとおりです。
api://<fully-qualified-domain-name>/<app-id>
-
api://
と<app-id>
(GUID) の間にfully-qualified-domain-name
を挿入します。 たとえば、「api://contoso.com/<app-id>
」のように入力します。 - localhost を使用している場合は、形式を
api://localhost:<port>/<app-id>
する必要があります。 たとえば、「api://localhost:3000/c6c1f32b-5e55-4997-881a-753cc1d563b7
」のように入力します。
その他のアプリケーション ID URI の詳細については、「 アプリケーション マニフェスト識別子Uris 属性」を参照してください。
注:
ドメインを所有しているにもかかわらず、そのドメインが既に所有されているというエラーが表示される場合は、「クイック スタート: カスタム ドメイン名を Azure Active Directory に追加する」の手順に従って登録し、この手順を繰り返します。 (このエラーは、Microsoft 365 テナントの管理者の資格情報でサインインしていない場合にも発生する可能性があります。手順 2 を参照してください。サインアウトし、管理者の資格情報を使用してもう一度サインインし、手順 3. のプロセスを繰り返します)。
-
アプリケーション ID URI には、アプリ ID (GUID) が形式
スコープを追加する
[ API の公開 ] ページで、[ スコープの追加] を選択します。
[ スコープの追加] ウィンドウが開きます。
[ スコープの追加] ウィンドウで、スコープ の属性を指定します。 次の表は、
profile
、openid
、Files.ReadWrite
、およびMail.Read
のアクセス許可を必要とするおよび Outlook アドインの値の例を示しています。 アドインに必要なアクセス許可に合わせてテキストを変更します。フィールド 説明 値 スコープ名 スコープの名前。 一般的なスコープの名前付け規則は resource.operation.constraint
。SSO の場合、これは access_as_user
に設定する必要があります。同意できるユーザー 管理者の同意が必要かどうか、またはユーザーが管理者の承認なしで同意できるかどうかを決定します。 SSO とサンプルを学習するには、これを [管理者とユーザー] に設定することをお勧めします。
高い特権を持つアクセス許可 の場合にのみ、[管理者] を選択します。同意の表示名管理 スコープの目的の簡単な説明は、管理者にのみ表示されます。 Read/write permissions to user files. Read permissions to user mail and profiles.
同意の説明管理 管理者のみが表示するスコープによって付与されるアクセス許可の詳細な説明。 Allow Office to have read/write permissions to all user files and read permissions to all user mail. Office can call the app's web APIs as the current user.
ユーザー同意表示名 スコープの目的の簡単な説明。 [管理者とユーザーに同意できるユーザー] を設定した場合にのみ、ユーザーに表示されます。 Read/write permissions to your files. Read permissions to your mail and profile.
ユーザーの同意の説明 スコープによって付与されるアクセス許可のより詳細な説明。 [管理者とユーザーに同意できるユーザー] を設定した場合にのみ、ユーザーに表示されます。 Allow Office to have read/write permissions to your files, and read permissions to your mail and profile.
[状態] を [有効] に設定し、[スコープの追加] を選択します。
定義した新しいスコープがウィンドウに表示されます。
注:
テキスト フィールドのすぐ下に表示される [スコープ名] のドメイン部分は、たとえば
api://localhost:6789/c6c1f32b-5e55-4997-881a-753cc1d563b7/access_as_user
のように手順で設定された [アプリケーション ID URI] と自動的に一致し、最後に/access_as_user
が追加されます。[クライアント アプリケーションの追加] を選択します。
[ クライアント アプリケーションの追加] ウィンドウが表示されます。
[ クライアント ID ] に「
ea5a67f6-b6f3-4338-b240-c655ddc3cc8e
」と入力します。 この値は、すべての Microsoft Office アプリケーション エンドポイントを事前に承認します。 Microsoft Teams内で使用するときに Office を事前に承認する場合は、1fec8e78-bce4-4aaf-ab1b-5451cc387264
(Microsoft Teams デスクトップと Teams モバイル) と5e3ce6c0-2b1f-4285-8d4b-75ee78787346
(Teams on the web) を追加します。注:
ea5a67f6-b6f3-4338-b240-c655ddc3cc8e
ID は、次のすべてのプラットフォームで Office を事前に承認します。 または、何らかの理由で一部のプラットフォームで Office への承認を拒否する場合は、次の ID の適切なサブセットを入力することもできます。 その場合は、承認を保留するプラットフォームの ID を除外します。 これらのプラットフォーム上のアドインのユーザーは Web API を呼び出せなくなりますが、アドイン内の他の機能は引き続き機能します。-
d3590ed6-52b3-4102-aeff-aad2292ab01c
(Microsoft Office) -
93d53678-613d-4013-afc1-62e9e444a0a5
(Office on the web) -
bc59ab01-8403-45c6-8796-ac3ef710b3e3
(Outlook on the web)
-
[ 承認されたスコープ] で、[
api://<fully-qualified-domain-name>/<app-id>/access_as_user
] チェック ボックスをオンにします。[アプリケーションの追加] を選択します。
Microsoft Graph のアクセス許可を追加する
左側のウィンドウで、[ API アクセス許可] を選択します。
[API アクセス許可] ウィンドウが開きます。
[アクセス許可を追加] を選択します。
[ API のアクセス許可の要求 ] ウィンドウが開きます。
[Microsoft Graph] を選択します。
[委任されたアクセス許可] を選択します。
[ アクセス許可の選択 ] 検索ボックスで、アドインで必要なアクセス許可を検索します。 たとえば、Outlook アドインの場合は、
profile
、openid
、Files.ReadWrite
、Mail.Read
を使用できます。注:
User.Read
アクセス許可は既定でリストされています。 必要なアクセス許可のみを要求することをお勧めします。アドインで実際に必要ない場合は、このアクセス許可のチェック ボックスをオフにすることをお勧めします。表示される各アクセス許可のチェック ボックスをオンにします。 アクセス許可は、各アクセス許可を選択しても一覧に表示されません。 アドインに必要なアクセス許可を選択したら、[ アクセス許可の追加] を選択します。
[ テナント名] の [管理者の同意の付与] を選択します。 表示される確認のために [ はい ] を選択します。
アクセス トークンのバージョンを構成する
アプリで許容されるアクセス トークンのバージョンを定義する必要があります。 この構成は、Azure Active Directory アプリケーション マニフェストで行われます。
アクセス トークンのバージョンを定義する
アクセス トークンのバージョンは、 任意の組織ディレクトリ (任意の Azure AD ディレクトリ - マルチテナント) と個人用 Microsoft アカウント (Skype、Xbox など) のアカウントの種類以外を選択した場合に変更される可能性があります。 次の手順を使用して、アクセス トークンのバージョンが Office SSO の使用に適していることを確認します。
左側のウィンドウで、[マニフェスト] を選択 します。
Azure Active Directory アプリケーション マニフェストが表示されます。
accessTokenAcceptedVersion
プロパティの値として 2 を入力します。[保存] を選択します。
マニフェストが正常に更新されたことを示すメッセージがブラウザにポップアップ表示されます。
おめでとうございます! アプリの登録を完了して、Office アドインの SSO を有効にしました。
アドインを構成する
コード エディターで複製プロジェクトの
\Begin
フォルダーを開きます。.ENV
ファイルを開き、Office-Add-in-NodeJS-SSO アプリの登録から前にコピーした値を使用します。 次のように値を設定します。名前 値 CLIENT_ID アプリ登録の概要ページからのアプリケーション (クライアント) ID。 CLIENT_SECRET [証明書] & [シークレット] ページから保存されたクライアント シークレット。 値は引用符で囲まないでください。 完了すると、ファイルは以下のようになります。
CLIENT_ID=8791c036-c035-45eb-8b0b-265f43cc4824 CLIENT_SECRET=X7szTuPwKNts41:-/fa3p.p@l6zsyI/p NODE_ENV=development SERVER_SOURCE=<https://localhost:3000>
アドイン マニフェスト ファイル "manifest\manifest_local.xml" を開き、ファイルの一番下までスクロールします。
</VersionOverrides>
終了タグのすぐ上に、次のマークアップがあります。<WebApplicationInfo> <Id>$app-id-guid$</Id> <Resource>api://localhost:3000/$app-id-guid$</Resource> <Scopes> <Scope>Files.Read</Scope> <Scope>profile</Scope> <Scope>openid</Scope> </Scopes> </WebApplicationInfo>
マークアップ内の両方の場所にあるプレースホルダー "$app-id-guid$" を、Office-Add-in-NodeJS-SSO アプリ登録の作成時にコピーしたアプリケーション ID に置き換えます。 "$" 記号は ID の一部ではないため、含めないでください。 これは、 のCLIENT_IDに使用した ID と同じです。ENV ファイル。
注:
<Resource> 値は、アドインを登録したときに設定したアプリケーション ID URI です。 <Scopes> セクションは、アドインが AppSource で販売されている場合にのみ同意ダイアログ ボックスを生成するために使用されます。
\public\javascripts\fallback-msal\authConfig.js
ファイルを開きます。 プレースホルダー "$app-id-guid$" を、前に作成した Office-Add-in-NodeJS-SSO アプリ登録から保存したアプリケーション ID に置き換えます。変更をファイルに保存します。
クライアント側のコーディング
Web サーバー REST API を呼び出す
コード エディターで、
public\javascripts\ssoAuthES6.js
ファイルを開きます。 これには、Trident (Internet エクスプローラー 11) Webview コントロールでも Promise が確実にサポートされるコードと、アドインの唯一のボタンにハンドラーを割り当てるためのOffice.onReady
呼び出しが含まれています。注:
名前が示すように、ssoAuthES6.js は JavaScript ES6 構文を使用します。これは、これは、
async
とawait
の使用こそが SSO API の本質的なシンプルさを最もよく示すためです。 localhost サーバーが起動されると、このファイルは ES5 構文に変換され、サンプルで Trident がサポートされます。getFileNameList
関数で、TODO 1
を次のコードに置き換えます。 このコードについては、以下の点に注意してください。- ユーザーが作業ウィンドウで [OneDrive ファイル名の取得] ボタンを選択すると、関数
getFileNameList
が呼び出されます。 - 呼び出す REST API を指定する
callWebServerAPI
関数を呼び出します。 これにより、ユーザーの OneDrive からのファイル名の一覧を含む JSON が返されます。 - JSON は、ドキュメント内のファイル名を一覧表示するために
writeFileNamesToOfficeDocument
関数に渡されます。
try { const jsonResponse = await callWebServerAPI('GET', '/getuserfilenames'); if (jsonResponse === null) { // Null is returned when a message was displayed to the user // regarding an authentication error that cannot be resolved. return; } await writeFileNamesToOfficeDocument(jsonResponse); showMessage('Your OneDrive filenames are added to the document.'); } catch (error) { console.log(error.message); showMessage(error.message); }
- ユーザーが作業ウィンドウで [OneDrive ファイル名の取得] ボタンを選択すると、関数
callWebServerAPI
関数で、TODO 2
を次のコードに置き換えます。 このコードについては、以下の点に注意してください。- 関数は
getAccessToken
を呼び出します。これは、トークンを取得するために必要に応じて Office SSO または MSAL フォールバックを使用してカプセル化する独自の関数です。 null トークンを返す場合、解決できない認証エラー条件のメッセージが表示されたため、関数も null を返します。 - 関数は、
fetch
API を使用して Web サーバーを呼び出し、成功した場合は JSON 本文を返します。
const accessToken = await getAccessToken(authSSO); if (accessToken === null) { return null; } const response = await fetch(path, { method: method, headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + accessToken, }, }); // Check for success condition: HTTP status code 2xx. if (response.ok) { return response.json(); }
- 関数は
callWebServerAPI
関数で、TODO 3
を次のコードに置き換えます。 このコードについては、以下の点に注意してください。- このコードは、SSO トークンの有効期限が切れたシナリオを処理します。 その場合は、更新されたトークンを取得するために
Office.auth.getAccessToken
を呼び出す必要があります。 最も簡単な方法は、再帰的な呼び出しを行って、Office.auth.getAccessToken
の新しい呼び出しを行う方法です。retryRequest
パラメーターを使用すると、再帰呼び出しが 1 回だけ試行されます。 -
TokenExpiredError
文字列は、期限切れのトークンが検出されるたびに Web サーバーによって設定されます。
// Check for fail condition: Is SSO token expired? If so, retry the call which will get a refreshed token. const jsonBody = await response.json(); if ( authSSO === true && jsonBody != null && jsonBody.type === 'TokenExpiredError' ) { if (!retryRequest) { return callWebServerAPI(method, path, true); // Try the call again. The underlying call to Office JS getAccessToken will refresh the token. } else { // Indicates a second call to retry and refresh the token failed. authSSO = false; return callWebServerAPI(method, path, true); // Try the call again, but now using MSAL fallback auth. } }
- このコードは、SSO トークンの有効期限が切れたシナリオを処理します。 その場合は、更新されたトークンを取得するために
callWebServerAPI
関数で、TODO 4
を次のコードに置き換えます。 このコードについては、以下の点に注意してください。-
Microsoft Graph
文字列は、Microsoft Graph の呼び出しが失敗するたびに Web サーバーによって設定されます。
// Check for fail condition: Did we get a Microsoft Graph API error, which is returned as bad request (403)? if (response.status === 403 && jsonBody.type === 'Microsoft Graph') { throw new Error('Microsoft Graph error: ' + jsonBody.errorDetails); }
-
callWebServerAPI
関数で、TODO 5
を次のコードに置き換えます。// Handle other errors. throw new Error( 'Unknown error from web server: ' + JSON.stringify(jsonBody) );
getAccessToken
関数で、TODO 6
を次のコードに置き換えます。 このコードについては、以下の点に注意してください。-
authSSO
は、SSO を使用している場合、または MSAL フォールバックを使用している場合は追跡されます。 SSO が使用されている場合、関数はOffice.auth.getAccessToken
を呼び出し、トークンを返します。 - エラーは、フォールバック MSAL 認証に切り替えた場合にトークンを返す
handleSSOErrors
関数によって処理されます。 - フォールバック認証では、MSAL ライブラリを使用してユーザーにサインインします。 アドイン自体は SPA であり、SPA アプリの登録を使用して Web サーバーにアクセスします。
if (authSSO) { try { // Get the access token from Office host using SSO. // Note that Office.auth.getAccessToken modifies the options parameter. Create a copy of the object // to avoid modifying the original object. const options = JSON.parse(JSON.stringify(ssoOptions)); const token = await Office.auth.getAccessToken(options); return token; } catch (error) { console.log(error.message); return handleSSOErrors(error); } } else { // Get access token through MSAL fallback. try { const accessToken = await getAccessTokenMSAL(); return accessToken; } catch (error) { console.log(error); throw new Error( 'Cannot get access token. Both SSO and fallback auth failed. ' + error ); } }
-
handleSSOErrors
関数で、TODO 7
を次のコードに置き換えます。 これらのエラーの詳細については、「Office アドインの SSO のトラブルシューティング (Troubleshoot SSO in Office Add-ins)」を参照してください。switch (error.code) { case 13001: // No one is signed into Office. If the add-in cannot be effectively used when no one // is logged into Office, then the first call of getAccessToken should pass the // `allowSignInPrompt: true` option. Since this sample does that, you should not see // this error. showMessage( 'No one is signed into Office. But you can use many of the add-ins functions anyway. If you want to log in, press the Get OneDrive File Names button again.' ); break; case 13002: // The user aborted the consent prompt. If the add-in cannot be effectively used when consent // has not been granted, then the first call of getAccessToken should pass the `allowConsentPrompt: true` option. showMessage( 'You can use many of the add-ins functions even though you have not granted consent. If you want to grant consent, press the Get OneDrive File Names button again.' ); break; case 13006: // Only seen in Office on the web. showMessage( 'Office on the web is experiencing a problem. Please sign out of Office, close the browser, and then start again.' ); break; case 13008: // Only seen in Office on the web. showMessage( 'Office is still working on the last operation. When it completes, try this operation again.' ); break; case 13010: // Only seen in Office on the web. showMessage( "Follow the instructions to change your browser's zone configuration." ); break;
TODO 8
を以下のコードに置き換えます。 処理できないエラーの場合、コードは MSAL を使用してフォールバック認証に切り替わります。default: //recursive call. // For all other errors, including 13000, 13003, 13005, 13007, 13012, and 50001, fall back // to MSAL sign-in. showMessage('SSO failed. Trying fallback auth.'); authSSO = false; return getAccessToken(false); } return null; // Return null for errors that show a message to the user.
Web サーバー REST API をコーディングする
Web サーバーは、クライアントが呼び出す REST API を提供します。 たとえば、REST API /getuserfilenames
は、ユーザーの OneDrive フォルダーからファイル名の一覧を取得します。 各 REST API 呼び出しでは、正しいクライアントがデータにアクセスしていることを確認するために、クライアントによるアクセス トークンが必要です。 アクセス トークンは、On-Behalf-Of フロー (OBO) を介して Microsoft Graph トークンと交換されます。 新しい Microsoft Graph トークンは、後続の API 呼び出しのために MSAL ライブラリによってキャッシュされます。 Web サーバーの外部に送信されることはありません。 詳細については、「中間層のアクセス トークン要求」を参照してください。
ルートを作成し、On-Behalf-Of フローを実装する
routes\getFilesRoute.js
ファイルを開き、TODO 9
を次のコードに置き換えます。 このコードについては、以下の点に注意してください。-
authHelper.validateJwt
を呼び出します。 これにより、アクセス トークンが有効であり、改ざんされていないことが保証されます。 - 詳細については、「 トークンの検証」を参照してください。
router.get( "/getuserfilenames", authHelper.validateJwt, async function (req, res) { // TODO 10: Exchange the access token for a Microsoft Graph token // by using the OBO flow. } );
-
TODO 10
を次のコードに置き換えます。 このコードについては、以下の点に注意してください。-
files.read
など、必要な最小スコープのみが要求されます。 - MSAL
authHelper
を使用して、acquireTokenOnBehalfOf
の呼び出しで OBO フローを実行します。
try { const authHeader = req.headers.authorization; let oboRequest = { oboAssertion: authHeader.split(' ')[1], scopes: ["files.read"], }; // The Scope claim tells you what permissions the client application has in the service. // In this case we look for a scope value of access_as_user, or full access to the service as the user. const tokenScopes = jwt.decode(oboRequest.oboAssertion).scp.split(' '); const accessAsUserScope = tokenScopes.find( (scope) => scope === 'access_as_user' ); if (!accessAsUserScope) { res.status(401).send({ type: "Missing access_as_user" }); return; } const cca = authHelper.getConfidentialClientApplication(); const response = await cca.acquireTokenOnBehalfOf(oboRequest); // TODO 11: Call Microsoft Graph to get list of filenames. } catch (err) { // TODO 12: Handle any errors. }
-
TODO 11
を次のコードに置き換えます。 このコードについては、以下の点に注意してください。- Microsoft Graph API 呼び出しの URL を構築し、
getGraphData
関数を使用して呼び出しを行います。 - HTTP 500 応答と詳細を送信してエラーを返します。
- 成功すると、ファイル名リストを含む JSON がクライアントに返されます。
// Minimize the data that must come from MS Graph by specifying only the property we need ("name") // and only the top 10 folder or file names. const rootUrl = '/me/drive/root/children'; // Note that the last parameter, for queryParamsSegment, is hardcoded. If you reuse this code in // a production add-in and any part of queryParamsSegment comes from user input, be sure that it is // sanitized so that it cannot be used in a Response header injection attack. const params = '?$select=name&$top=10'; const graphData = await getGraphData( response.accessToken, rootUrl, params ); // If Microsoft Graph returns an error, such as invalid or expired token, // there will be a code property in the returned object set to a HTTP status (e.g. 401). // Return it to the client. On client side it will get handled in the fail callback of `makeWebServerApiCall`. if (graphData.code) { res .status(403) .send({ type: "Microsoft Graph", errorDetails: "An error occurred while calling the Microsoft Graph API.\n" + graphData, }); } else { // MS Graph data includes OData metadata and eTags that we don't need. // Send only what is actually needed to the client: the item names. const itemNames = []; const oneDriveItems = graphData["value"]; for (let item of oneDriveItems) { itemNames.push(item["name"]); } res.status(200).send(itemNames); } // TODO 12: Check for expired token.
- Microsoft Graph API 呼び出しの URL を構築し、
TODO 12
を次のコードに置き換えます。 このコードでは、クライアントが新しいトークンを要求して再度呼び出すことができるため、トークンの有効期限が切れたかどうかを特に確認します。} catch (err) { // On rare occasions the SSO access token is unexpired when Office validates it, // but expires by the time it is used in the OBO flow. Microsoft identity platform will respond // with "The provided value for the 'assertion' is not valid. The assertion has expired." // Construct an error message to return to the client so it can refresh the SSO token. if (err.errorMessage.indexOf('AADSTS500133') !== -1) { res.status(401).send({ type: "TokenExpiredError", errorDetails: err }); } else { res.status(403).send({ type: "Unknown", errorDetails: err }); } }
このサンプルでは、MSAL によるフォールバック認証と Office 経由の SSO 認証の両方を処理する必要があります。 サンプルでは最初に SSO を試し、サンプルが SSO を使用しているか、フォールバック認証に切り替えた場合、ファイルの上部にある authSSO
ブール値が追跡されます。
プロジェクトを実行する
結果を確認できるように、OneDrive 内にファイルがいくつかあることを確認します。
\Begin
フォルダーのルートでコマンド プロンプトを開きます。コマンド
npm install
を実行して、すべてのパッケージの依存関係をインストールします。npm start
コマンドを実行して中間層サーバーを起動します。アドインを Office アプリケーション (Excel、Word、または PowerPoint) にサイドロードして、テストをする必要があります。 手順はプラットフォームによって異なります。 「テスト用に Office アドインをサイドロードする」に手順へのリンクがあります。
Office アプリケーションの [ホーム] リボンで [アドインの表示] ボタン (SSO Node.js グループ内) を選択して、作業ウィンドウ アドインを開きます。
[OneDrive ファイル名の取得] ボタンをクリックします。 Microsoft 365 Educationまたは職場アカウント、または Microsoft アカウントを使用して Office にログインしていて、SSO が正常に動作している場合は、OneDrive for Business内の最初の 10 個のファイル名とフォルダー名がドキュメントに挿入されます。 (初回は 15 秒ほどかかる場合があります。ログインしていない場合、または SSO をサポートしていないシナリオや、何らかの理由で SSO が機能しない場合は、サインインするように求められます。 サインインすると、ファイル名とフォルダー名が表示されます。
注:
以前に別の ID で Office にサインインしており、その時点で開いていた一部の Office アプリケーションがまだ開いている場合、Office が ID を変更したかのように見えても、確実に ID を変更できていない場合があります。 これが発生すると、Microsoft Graph の呼び出しが失敗するか、以前の ID のデータが返される場合があります。 これを防ぐには、必ず他のすべての Office アプリケーションを閉じてから、[OneDrive ファイル名の取得] を押してください。
プロジェクトの実行を停止する
中間層サーバーを停止してアドインをアンインストールする準備ができたら、次の手順に従います。
次のコマンドを実行して、中間層サーバーを停止します。
npm stop
アドインをアンインストールまたは削除するには、詳細に使用した特定のサイドロードに関する記事を参照してください。
セキュリティに関する注意事項
getFilesroute.js
の/getuserfilenames
ルートでは、リテラル文字列を使用して Microsoft Graph の呼び出しを構成します。 文字列の任意の部分がユーザー入力から取得されるように呼び出しを変更する場合は、応答ヘッダーインジェクション攻撃で使用できないように入力をサニタイズします。app.js
では、スクリプトに対して次のコンテンツ セキュリティ ポリシーが適用されます。 アドインのセキュリティニーズに応じて、追加の制限を指定することもできます。"Content-Security-Policy": "script-src https://appsforoffice.microsoft.com https://ajax.aspnetcdn.com https://alcdn.msauth.net " + process.env.SERVER_SOURCE,
Microsoft ID プラットフォームドキュメントのセキュリティのベスト プラクティスに常に従ってください。
Office Add-ins