次の方法で共有


チュートリアル: App Service からバックエンド API を介して Microsoft Graph に認証をフローする

フロントエンド アプリのユーザー資格情報を受け入れるようにバックエンド App Service を作成して構成し、その資格情報をダウンストリーム Azure サービスと交換する方法について説明します。 これにより、ユーザーはフロントエンド App Service にサインインし、その資格情報をバックエンド App Service に渡し、同じ ID で Azure サービスにアクセスできます。

このチュートリアルでは、以下の内容を学習します。

  • バックエンド認証アプリを構成して、ダウンストリーム Azure サービスのスコープが設定されたトークンを提供する
  • JavaScript コードを使用して、 サインインしているユーザーのアクセス トークン をダウンストリーム サービスの新しいトークンと交換します。
  • JavaScript コードを使用してダウンストリーム サービスにアクセスします。

[前提条件]

このチュートリアルを開始する前に、セキュリティで 保護された JavaScript アプリからユーザーとして Microsoft Graph にアクセスする前に、チュートリアルの最後にリソースを削除しないでください。 このチュートリアルでは、2 つの App Services とそれに対応する認証アプリがあることを前提としています。

前のチュートリアルでは、Azure CLI のシェルとして Azure Cloud Shell を使用しました。 このチュートリアルでは、引き続きその使用方法を説明します。

アーキテクチャ

このチュートリアルでは、フロントエンド アプリによって提供されたユーザー資格情報をバックエンド アプリに渡し、次に Azure サービスに渡す方法について説明します。 このチュートリアルでは、ダウンストリーム サービスは Microsoft Graph です。 ユーザーの資格情報は、Microsoft Graph からプロファイルを取得するために使用されます。

サインインしているユーザーの代わりに Microsoft Graph に接続する App Service を表すアーキテクチャイメージ。

ユーザーがこのアーキテクチャで Microsoft Graph 情報を取得するための認証フロー:

前のチュートリアル で取り上げた内容:

  1. Active Directory を ID プロバイダーとして使用するように構成されたフロントエンド App Service にユーザーをサインインさせます。
  2. フロントエンド App Service は、ユーザーのトークンをバックエンド App Service に渡します。
  3. バックエンド アプリは、フロントエンドが API 要求を行えるようにセキュリティで保護されています。 ユーザーのアクセス トークンには、バックエンド API の対象ユーザーと user_impersonationのスコープがあります。
  4. バックエンド アプリの登録には、スコープ User.Readを持つ Microsoft Graph が既に含まれます。 既定では、これはすべてのアプリ登録に追加されます。
  5. 前のチュートリアルの最後に、Graph が接続されていないため、 のプロファイルがフロントエンド アプリに返されました。

このチュートリアルでは、アーキテクチャを拡張します。

  1. バックエンド アプリのユーザーの同意画面をバイパスするための管理者の同意を付与します。
  2. フロントエンド アプリから送信されたアクセス トークンを、Microsoft Graph に必要なアクセス許可を持つアクセス トークンに変換するようにアプリケーション コードを変更します。
  3. バックエンド アプリが、新しいトークンを Microsoft Graph などのダウンストリーム Azure サービスのスコープで使用するために、トークンを交換するコードを提供します。
  4. バックエンド アプリで 新しいトークンを使用 して、現在の認証ユーザーとしてダウンストリーム サービスにアクセスするためのコードを提供します。
  5. を使用してバックエンド アプリをaz webapp upします。
  6. このチュートリアルの最後に、Graph が接続されているため、 実際 のプロファイルがフロントエンド アプリに返されます。

このチュートリアルでは、次の操作は行いません。

  • 前のチュートリアルからフロントエンド アプリを変更します。
  • User.Readはすべての認証アプリに既定で追加されるため、バックエンド認証アプリのスコープアクセス許可を変更します。

前のチュートリアルでは、ユーザーがフロントエンド アプリにサインインしたときに、ユーザーの同意を求めるポップアップが表示されました。

このチュートリアルでは、Microsoft Graph からユーザー プロファイルを読み取るために、バックエンド アプリは、サインインしているユーザーの アクセス トークン を、Microsoft Graph に必要なアクセス許可を持つ新しいアクセス トークンと交換する必要があります。 ユーザーはバックエンド アプリに直接接続されていないため、対話形式で同意画面にアクセスすることはできません。 これを回避するには、 管理者の同意を付与するために Microsoft Entra ID でバックエンド アプリのアプリ登録を構成する必要があります。 これは、通常、Active Directory 管理者が行う設定の変更です。

  1. Azure ポータルを開き、リサーチに関連するバックエンドの App Service を検索します。

  2. [設定] -> [認証] セクションを見つけます。

  3. ID プロバイダーを選択して認証アプリに移動します。

  4. 認証アプリで、[ 管理] -> [API のアクセス許可] を選択します。

  5. [ 既定のディレクトリに管理者の同意を付与する] を選択します

    管理者の同意ボタンが強調表示されている Azure portal 認証アプリのスクリーンショット。

  6. ポップアップ ウィンドウで、[ はい ] を選択して同意を確認します。

  7. [状態] 列に [既定のディレクトリに対して付与] と表示されていることを確認します。 この設定により、バックエンド アプリはサインインしているユーザーに同意画面を表示する必要がなくなり、アクセス トークンを直接要求できます。 サインインしているユーザーは、アプリの登録が作成される既定のスコープであることから、User.Read スコープ設定にアクセスできます。

    [状態] 列に管理者の同意が付与されている Azure portal 認証アプリのスクリーンショット。

2. npm パッケージをインストールする

前のチュートリアルでは、Azure portal で ID プロバイダーを構成することによって認証のみが提供されたため、バックエンド アプリでは認証に npm パッケージは必要ありませんでした。 このチュートリアルでは、バックエンド API のサインインしているユーザーのアクセス トークンを、スコープ内の Microsoft Graph とアクセス トークンと交換する必要があります。 この交換では App Service 認証が使用されなくなり、Microsoft Entra ID と MSAL.js が直接使用されるため、この交換は 2 つのライブラリで完了します。

  1. Azure Cloud Shell を開き、サンプル ディレクトリのバックエンド アプリに変更します。

    cd js-e2e-web-app-easy-auth-app-to-app/backend
    
  2. Azure MSAL npm パッケージをインストールします。

    npm install @azure/msal-node
    
  3. Microsoft Graph npm パッケージをインストールします。

    npm install @microsoft/microsoft-graph-client
    

3. 現在のトークンを Microsoft Graph トークンと交換するコードを追加する

この手順を完了するためのソース コードが用意されています。 これを含めるには、次の手順を使用します。

  1. ./src/server.js ファイルを開きます。

  2. ファイルの先頭にある次の依存関係のコメントを解除します。

    import { getGraphProfile } from './with-graph/graph';
    
  3. 同じファイルで、 graphProfile 変数のコメントを解除します。

    let graphProfile={};
    
  4. 同じファイルで、getGraphProfile ルート内の次のget-profile行のコメントを解除して、Microsoft Graph からプロファイルを取得します。

    // where did the profile come from
    profileFromGraph=true;
    
    // get the profile from Microsoft Graph
    graphProfile = await getGraphProfile(accessToken);
    
    // log the profile for debugging
    console.log(`profile: ${JSON.stringify(graphProfile)}`);
    
  5. 変更を保存します :Ctrl + s

  6. バックエンド アプリを再デプロイします。

    az webapp up --resource-group myAuthResourceGroup --name <back-end-app-name> 
    
    

4. バックエンド コードを調べて、バックエンド API トークンを Microsoft Graph トークンと交換する

Microsoft Graph トークンのバックエンド API 対象ユーザー トークンを変更するには、バックエンド アプリでテナント ID を検索し、MSAL.js 構成オブジェクトの一部として使用する必要があります。 Microsoft を ID プロバイダーとして構成したバックエンド アプリは、テナント ID とその他のいくつかの必須値が App Service アプリの設定に既に含まれています。

サンプル アプリでは、次のコードが既に提供されています。 この機能を必要とする他のアプリにこの作業を適用できるように、その理由と動作方法を理解する必要があります。

テナント ID を取得するためのコードを調べる

  1. ./backend/src/with-graph/auth.js ファイルを開きます。

  2. getTenantId()関数を確認します。

    export function getTenantId() {
    
        const openIdIssuer = process.env.WEBSITE_AUTH_OPENID_ISSUER;
        const backendAppTenantId = openIdIssuer.replace(/https:\/\/sts\.windows\.net\/(.{1,36})\/v2\.0/gm, '$1');
    
        return backendAppTenantId;
    }
    
  3. この関数は、 WEBSITE_AUTH_OPENID_ISSUER 環境変数から現在のテナント ID を取得します。 ID は、正規表現を使用して変数から解析されます。

MSAL.js を使用して Graph トークンを取得するコードを検査する

  1. 引き続き ./backend/src/with-graph/auth.js ファイルで、getGraphToken() 関数を確認します。

  2. MSAL.js 構成オブジェクトをビルドし、MSAL 構成を使用して clientCredentialAuthority を作成します。 On-Behalf-Of 要求を構成します。 次に、acquireTokenOnBehalfOf を使用して、バックエンド API アクセス トークンを Graph アクセス トークンと交換します。

    // ./backend/src/auth.js
    // Exchange current bearerToken for Graph API token
    // Env vars were set by App Service
    export async function getGraphToken(backEndAccessToken) {
    
        const config = {
            // MSAL configuration
            auth: {
                // the backend's authentication CLIENT ID 
                clientId: process.env.WEBSITE_AUTH_CLIENT_ID,
                // the backend's authentication CLIENT SECRET 
                clientSecret: process.env.MICROSOFT_PROVIDER_AUTHENTICATION_SECRET,
                // OAuth 2.0 authorization endpoint (v2)
                // should be: https://login.microsoftonline.com/BACKEND-TENANT-ID
                authority: `https://login.microsoftonline.com/${getTenantId()}`
            },
            // used for debugging
            system: {
                loggerOptions: {
                    loggerCallback(loglevel, message, containsPii) {
                        console.log(message);
                    },
                    piiLoggingEnabled: true,
                    logLevel: MSAL.LogLevel.Verbose,
                }
            }
        };
    
        const clientCredentialAuthority = new MSAL.ConfidentialClientApplication(config);
    
        const oboRequest = {
            oboAssertion: backEndAccessToken,
            // this scope must already exist on the backend authentication app registration 
            // and visible in resources.azure.com backend app auth config
            scopes: ["https://graph.microsoft.com/.default"]
        }
    
        // This example has App service validate token in runtime
        // from headers that can't be set externally
    
        // If you aren't using App service's authentication, 
        // you must validate your access token yourself
        // before calling this code
        try {
            const { accessToken } = await clientCredentialAuthority.acquireTokenOnBehalfOf(oboRequest);
            return accessToken;
        } catch (error) {
            console.log(`getGraphToken:error.type = ${error.type}  ${error.message}`);
        }
    }
    

5. バックエンド コードを調べて、新しいトークンで Microsoft Graph にアクセスする

フロントエンド アプリケーションにサインインしたユーザーとして Microsoft Graph にアクセスするには、次のような変更が加えられます。

  • User.Readの必要なスコープを使用して、ダウンストリーム サービスである Microsoft Graph に対する API アクセス許可を持つ Active Directory アプリ登録の構成。
  • バックエンド アプリのユーザーの同意画面をバイパスするための管理者の同意を付与します。
  • フロントエンド アプリから送信されたアクセス トークンを、ダウンストリーム サービスである Microsoft Graph に必要なアクセス許可を持つアクセス トークンに変換するようにアプリケーション コードを変更します。

コードに Microsoft Graph 用の正しいトークンが用意されたので、それを使用して Microsoft Graph へのクライアントを作成し、ユーザーのプロファイルを取得します。

  1. ./backend/src/graph.jsを開いてください。

  2. getGraphProfile()関数でトークンを取得し、トークンから認証されたクライアントを取得し、プロファイルを取得します。

    // 
    import graph from "@microsoft/microsoft-graph-client";
    import { getGraphToken } from "./auth.js";
    
    // Create client from token with Graph API scope
    export function getAuthenticatedClient(accessToken) {
        const client = graph.Client.init({
            authProvider: (done) => {
                done(null, accessToken);
            }
        });
    
        return client;
    }
    export async function getGraphProfile(accessToken) {
        // exchange current backend token for token with 
        // graph api scope
        const graphToken = await getGraphToken(accessToken);
    
        // use graph token to get Graph client
        const graphClient = getAuthenticatedClient(graphToken);
    
        // get profile of user
        const profile = await graphClient
            .api('/me')
            .get();
    
        return profile;
    }
    

6. 変更をテストする

  1. ブラウザーでフロントエンド Web サイトを使います。 トークンの有効期限が切れている場合は、トークンの更新が必要になる場合があります。

  2. [Get user's profile] を選択します。 これにより、ベアラー トークンの認証がバックエンドに渡されます。

  3. バックエンド エンドは、アカウントの 実際 の Microsoft Graph プロファイルで応答します。

    バックエンド アプリから実際のプロファイルを正常に取得した後のフロントエンド アプリケーションを示す Web ブラウザーのスクリーンショット。

7. クリーンアップ

前の手順では、リソース グループ内に Azure リソースを作成しました。

  1. Cloud Shell で次のコマンドを実行して、リソース グループを削除します。 このコマンドの実行には、少し時間がかかる場合があります。

    az group delete --name myAuthResourceGroup
    
  2. 認証アプリのクライアント ID を使います。これは、バックエンド アプリとフロントエンド アプリの Enable authentication and authorization セクションで以前に確認し、メモしておいたものです。

  3. フロントエンド アプリとバックエンド アプリの両方のアプリ登録を削除します。

    # delete app - do this for both frontend and backend client ids
    az ad app delete <client-id>
    

よく寄せられる質問

80049217エラーが発生しました。どういう意味ですか?

このエラー CompactToken parsing failed with error code: 80049217、バックエンド App Service が Microsoft Graph トークンを返す権限を持っていないことを意味します。 このエラーは、アプリの登録に User.Read アクセス許可がないために発生します。

AADSTS65001エラーが発生しました。どういう意味ですか?

このエラー AADSTS65001: The user or administrator has not consented to use the application with ID \<backend-authentication-id>. Send an interactive authorization request for this user and resource、バックエンド認証アプリが管理者の同意用に構成されていないことを意味します。 バックエンド アプリのログにエラーが表示されるため、フロントエンド アプリケーションは、フロントエンド アプリにプロファイルが表示されなかった理由をユーザーに通知できません。

ユーザーとして別のダウンストリーム Azure サービスに接続するにはどうすればよいですか?

このチュートリアルでは、 Microsoft Graph に対して認証された API アプリを示しますが、ユーザーに代わってすべての Azure サービスにアクセスするために同じ一般的な手順を適用できます。

  1. フロントエンド アプリケーションに変更はありません。 バックエンドの認証アプリの登録とバックエンド アプリのソース コードに対する変更のみ。
  2. アクセスしたいダウンストリームサービス用のトークンを得るために、バックエンドAPIのスコープを持つユーザーのトークンを交換します。
  3. ダウンストリーム サービスの SDK でトークンを使用してクライアントを作成します。
  4. ダウンストリーム クライアントを使用してサービス機能にアクセスします。

次のステップ