チュートリアル: ユーザーのサインインを処理して、JavaScript シングルページ アプリケーション から Microsoft Graph API を呼び出す

このチュートリアルでは、ユーザーのサインインを処理し、OAuth 2.0 の暗黙的なフローを使用して Microsoft Graph を呼び出す JavaScript シングルページ アプリケーション (SPA) を作成します。 この SPA では、SPA の暗黙的な許可フローを使用する MSAL.js v1.x を使用します。 すべての新しいアプリケーションで、PKCE および CORS を用いた MSAL.js 2.x と承認コード フローを使用します。 承認コード フローは、暗黙的なフローよりも多くのセキュリティを提供します。

このチュートリアルの内容:

  • npm を使用して JavaScript プロジェクトを作成する
  • Azure portal でアプリケーションを登録する
  • ユーザーのサインインとサインアウトをサポートするコードを追加する
  • Microsoft Graph API を呼び出すコードを追加する
  • アプリケーションをテストする
  • プロセスがバックグラウンドでどのように動作するかを把握する

このチュートリアルが完了すると、次のフォルダーとファイル構造が作成されます (作成順に一覧表示されます)。

sampleApp/
├── JavaScriptSPA/
│   ├── authConfig.js
│   ├── authPopup.js
│   ├── graph.js
│   ├── graphConfig.js
│   ├── index.html
│   └── ui.js
├── package.json
├── package-lock.json
├── node_modules/
│   └── ...    
└── server.js
 

前提条件

  • ローカル Web サーバーを実行するための Node.js
  • プロジェクト ファイルを編集するための Visual Studio Code と別のエディター。
  • 最新の Web ブラウザー このチュートリアルで作成するアプリには ES6 規則が使用され、"Internet Explorer はサポートされていません"。

このサンプル アプリのしくみ

このチュートリアルで生成されたサンプル アプリの動作を示す図。

このチュートリアルで作成したアプリケーションでは、JavaScript SPA が Microsoft Graph API に対してクエリを実行できるようになります。 このクエリ処理は、Microsoft ID プラットフォームからトークンを受け入れるように設定された Web API でも機能します。 ユーザーのサインイン後、SPA によってアクセス トークンが要求され、Authorization ヘッダーを介して HTTP 要求に追加されます。 SPA は、このトークンを使用して、Microsoft Graph API を介してユーザーのプロファイルとメールアドレスを取得します。

トークンの取得と更新は、Microsoft Authentication Library (MSAL) for JavaScript で処理されます。

Web サーバーまたはプロジェクトの設定

必要に応じて、プロジェクト ファイルをダウンロードできます。

コード サンプルを実行する前に構成する場合は、登録手順に進みます。

プロジェクトを作成する

  1. Node.js がインストールされていることを確認してから、アプリケーションをホストするフォルダーを作成します。 フォルダーの名前を「sampleApp」にします。 このフォルダーには、index.html ファイルを提供する Express Web サーバーが作成されます。

  2. ターミナル (Visual Studio Code 統合ターミナルなど) を使用して、プロジェクト フォルダーを見つけて移動します。 それから、次のように入力します。

    npm init
    
  3. アプリケーションを作成するための一連のプロンプトが表示されます。 sampleApp フォルダーがすべて小文字になっていることに注意してください。 かっこ () 内の項目は、既定で生成されます。

    package name: (sampleapp)
    version: (1.0.0)
    description:
    entry point: (index.js)
    test command:
    git repository:
    keywords:
    author:
    license: (ISC)
    

    自由に試してみてください。 ただし、このチュートリアルの目的では、何も入力する必要はありません。 Enter キーを押して、次のプロンプトに進みます。

  4. 前の手順で値を入力しなかった場合、最後の同意プロンプトに次の出力が表示されます。

    {
      "name": "sampleapp",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "author": "",
      "license": "ISC"
    }
    
    
    Is this OK? (yes)
    

    Enter キーを押すと、package.json というファイルに JSON が書き込まれます。

  5. 次のコードを入力し、必要な依存関係をインストールします。

    npm install express --save
    npm install morgan --save
    

    Express.js は、Web サーバーと API の作成を簡略化する Node.js モジュールです。 Morgan.js は、HTTP 要求とエラーをログに記録するために使用されます。 インストールすると、package-lock.json ファイルと node_modules フォルダーが作成されます。

  6. 現在のフォルダー に server.js という名前の .js ファイルを作成し、次のコードを追加します。

    const express = require('express');
    const morgan = require('morgan');
    const path = require('path');
    
    //Initialize Express.
    const app = express();
    
    // Initialize variables.
    const port = 3000; // process.env.PORT || 3000;
    
    // Configure the morgan module to log all requests.
    app.use(morgan('dev'));
    
    // Set the front-end folder to serve public assets.
    app.use(express.static('JavaScriptSPA'))
    
    app.get('*', function (req, res) {
        res.sendFile(path.join(__dirname + '/JavaScriptSPA/index.html'));
    });
    
    // Start the server.
    app.listen(port);
    console.log('Listening on port ' + port + '...');
    

これで、SPA を提供するサーバーが完成しました。 この時点で、フォルダー構造は次のようになります。

sampleApp/
├── package.json
├── package-lock.json
├── node_modules/
│   └── ...    
└── server.js

次の手順では、JavaScript SPA 用の新しいフォルダーを作成し、ユーザー インターフェイス (UI) を設定します。

ヒント

Azure Active Directory (Azure AD) アカウントを設定するときに、テナントを作成します。 これは、組織をデジタルで表現したものです。 主に、Microsoft.com などのドメインに関連付けられています。 アプリケーションが複数のテナントを操作する方法については、アプリケーション モデルに関するページを参照してください。

SPA UI を作成する

  1. 新しいフォルダー JavaScriptSPA を作成し、そのフォルダーに移動します。

  2. SPA の index.html ファイルを作成します。 このファイルは、Bootstrap 4 フレームワークを使用して構築された UI を実装します。 また、このファイルは、構成、認証、API 呼び出し用のスクリプト ファイルのインポートも行います。

    Index.html ファイルに、次のコードを追加します。

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
        <title>Quickstart | MSAL.JS Vanilla JavaScript SPA</title>
    
        <!-- msal.js with a fallback to backup CDN -->
          <script src="https://alcdn.msauth.net/browser/2.30.0/js/msal-browser.js"
     integrity="sha384-L8LyrNcolaRZ4U+N06atid1fo+kBo8hdlduw0yx+gXuACcdZjjquuGZTA5uMmUdS"
     crossorigin="anonymous"></script> 
    
        <!-- adding Bootstrap 4 for UI components  -->
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-o4ufwq3oKqc7IoCcR08YtZXmgOljhTggRwxP2CLbSqeXGtitAxwYaUln/05nJjit" crossorigin="anonymous">
      </head>
      <body>
        <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
          <a class="navbar-brand" href="/">MS Identity Platform</a>
          <div class="btn-group ml-auto dropleft">
            <button type="button" id="signIn" class="btn btn-secondary" onclick="signIn()">Sign In</button>
            <button type="button" id="signOut" class="btn btn-success d-none" onclick="signOut()">Sign Out</button>
        </div>
        </nav>
        <br>
        <h5 class="card-header text-center">Vanilla JavaScript SPA calling MS Graph API with MSAL.JS</h5>
        <br>
        <div class="row" style="margin:auto" >
        <div id="card-div" class="col-md-3 d-none">
        <div class="card text-center">
          <div class="card-body">
            <h5 class="card-title" id="welcomeMessage">Please sign-in to see your profile and read your mails</h5>
            <div id="profile-div"></div>
            <br>
            <br>
            <button class="btn btn-primary" id="seeProfile" onclick="seeProfile()">See Profile</button>
            <br>
            <br>
            <button class="btn btn-primary d-none" id="readMail" onclick="readMail()">Read Mails</button>
          </div>
        </div>
        </div>
        <br>
        <br>
          <div class="col-md-4">
            <div class="list-group" id="list-tab" role="tablist">
            </div>
          </div>
          <div class="col-md-5">
            <div class="tab-content" id="nav-tabContent">
            </div>
          </div>
        </div>
        <br>
        <br>
    
        <!-- importing bootstrap.js and supporting .js libraries -->
        <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
        <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
    
        <!-- importing app scripts (load order is important) -->
        <script type="text/javascript" src="./authConfig.js"></script>
        <script type="text/javascript" src="./graphConfig.js"></script>
        <script type="text/javascript" src="./ui.js"></script>
    
        <!-- replace the next line with authRedirect.js if you want to use the redirect flow -->
        <!-- <script type="text/javascript" src="./authRedirect.js"></script>   -->
        <script type="text/javascript" src="./authPopup.js"></script>
        <script type="text/javascript" src="./graph.js"></script>
      </body>
    </html>
    
  3. ui.js というファイルを作成し、次のコードを追加して、ドキュメント オブジェクト モデル (DOM) 要素にアクセスして更新します。

    // Select DOM elements to work with
    const welcomeDiv = document.getElementById("welcomeMessage");
    const signInButton = document.getElementById("signIn");
    const signOutButton = document.getElementById('signOut');
    const cardDiv = document.getElementById("card-div");
    const mailButton = document.getElementById("readMail");
    const profileButton = document.getElementById("seeProfile");
    const profileDiv = document.getElementById("profile-div");
    
    function showWelcomeMessage(account) {
      // Reconfiguring DOM elements
      cardDiv.classList.remove('d-none');
      welcomeDiv.innerHTML = `Welcome ${account.name}`;
      signInButton.classList.add('d-none');
      signOutButton.classList.remove('d-none');
    }
    
    function updateUI(data, endpoint) {
      console.log('Graph API responded at: ' + new Date().toString());
    
      if (endpoint === graphConfig.graphMeEndpoint) {
        const title = document.createElement('p');
        title.innerHTML = "<strong>Title: </strong>" + data.jobTitle;
        const email = document.createElement('p');
        email.innerHTML = "<strong>Mail: </strong>" + data.mail;
        const phone = document.createElement('p');
        phone.innerHTML = "<strong>Phone: </strong>" + data.businessPhones[0];
        const address = document.createElement('p');
        address.innerHTML = "<strong>Location: </strong>" + data.officeLocation;
        profileDiv.appendChild(title);
        profileDiv.appendChild(email);
        profileDiv.appendChild(phone);
        profileDiv.appendChild(address);
    
      } else if (endpoint === graphConfig.graphMailEndpoint) {
          if (data.value.length < 1) {
            alert("Your mailbox is empty!")
          } else {
            const tabList = document.getElementById("list-tab");
            tabList.innerHTML = ''; // clear tabList at each readMail call
            const tabContent = document.getElementById("nav-tabContent");
    
            data.value.map((d, i) => {
              // Keeping it simple
              if (i < 10) {
                const listItem = document.createElement("a");
                listItem.setAttribute("class", "list-group-item list-group-item-action")
                listItem.setAttribute("id", "list" + i + "list")
                listItem.setAttribute("data-toggle", "list")
                listItem.setAttribute("href", "#list" + i)
                listItem.setAttribute("role", "tab")
                listItem.setAttribute("aria-controls", i)
                listItem.innerHTML = d.subject;
                tabList.appendChild(listItem)
    
                const contentItem = document.createElement("div");
                contentItem.setAttribute("class", "tab-pane fade")
                contentItem.setAttribute("id", "list" + i)
                contentItem.setAttribute("role", "tabpanel")
                contentItem.setAttribute("aria-labelledby", "list" + i + "list")
                contentItem.innerHTML = "<strong> from: " + d.from.emailAddress.address + "</strong><br><br>" + d.bodyPreview + "...";
                tabContent.appendChild(contentItem);
              }
            });
          }
      }
    }
    

アプリケーションを登録する

認証を続行する前に、Azure AD でアプリケーションを登録します。

  1. Azure portal にサインインします。

  2. [Azure Active Directory] に移動します。

  3. 左側のパネルの [管理] で、[アプリの登録] を選択します。 その後、上部のメニュー バーで、[新規登録] を選択します。

  4. [名前] にアプリケーションの名前を入力します (sampleApp など)。 後で名前を変えることもできます。

  5. [サポートされているアカウントの種類] で、 [この組織のディレクトリ内のアカウントのみ] を選択します。

  6. [リダイレクト URI] セクションで、ドロップダウン リストから Web プラットフォームを選択します。

    右側に、「http://localhost:3000/」と入力します。

  7. [登録] を選択します。

    アプリケーションの [概要] ページが開きます。 [アプリケーション (クライアント) ID][ディレクトリ (テナント) ID] の値をメモします。 後の手順で authConfig.js ファイルを作成する際に、その両方が必要になります。

  8. [管理] で、 [認証] を選択します。

  9. [Implicit grant and hybrid flows](暗黙的な許可およびハイブリッド フロー) セクションで、 [ID トークン][アクセス トークン] を選択します。 このアプリではユーザーのサインインを実行して API を呼び出す必要があるため、ID トークンとアクセス トークンが必要です。

  10. [保存] を選択します。 [概要] ページに戻るには、左側のパネルで選択します。

[概要] ページに移動して、[リダイレクト URI を追加する] を選択することで、リダイレクト URI をいつでも変更できます。

JavaScript SPA を構成する

  1. JavaScriptSPA フォルダーで、新しいファイル authConfig.js を作成します。 その後、次のコードをコピーします。 このコードには、認証の構成パラメーター (クライアント ID、テナント ID、リダイレクト URI) が含まれています。

      const msalConfig = {
        auth: {
          clientId: "Enter_the_Application_Id_Here",
          authority: "Enter_the_Cloud_Instance_Id_Here/Enter_the_Tenant_Info_Here",
          redirectUri: "Enter_the_Redirect_URI_Here",
        },
        cache: {
          cacheLocation: "sessionStorage", // This configures where your cache will be stored
          storeAuthStateInCookie: false, // Set this to "true" if you're having issues on Internet Explorer 11 or Edge
        }
      };
    
      // Add scopes for the ID token to be used at Microsoft identity platform endpoints.
      const loginRequest = {
        scopes: ["openid", "profile", "User.Read"]
      };
    
      // Add scopes for the access token to be used at Microsoft Graph API endpoints.
      const tokenRequest = {
        scopes: ["Mail.Read"]
      };
    
  2. msalConfig セクションの値を変更します。 これらの値については、アプリケーションの [概要] ページを参照してください。

    • Enter_the_Application_Id_Here は、登録したアプリケーションのアプリケーション (クライアント) ID の値です。

    • Enter_the_Cloud_Instance_Id_Here は、Azure クラウドのインスタンスです。 メイン (グローバル) Azure クラウドの場合は、「https://login.microsoftonline.com」と入力します。 各国のクラウド (中国など) の場合は、「各国のクラウド」を参照してください。

    • Enter_the_Tenant_info_hereディレクトリ (テナント) ID (GUID) またはテナント名の値 (contoso.onmicrosoft.com など) に置き換えます。

    • Enter_the_Redirect_URI_Here は、前のセクションで設定した既定の URL http://localhost:3000/ です。

ヒント

アプリケーションでサポートする内容に応じて、Enter_the_Tenant_info_here にはその他のオプションがあります。

  • アプリケーションで "任意の組織のディレクトリ内のアカウント" がサポートされる場合は、この値を organizations に置き換えます。
  • アプリケーションで "任意の組織のディレクトリ内のアカウントと、個人用の Microsoft アカウント" がサポートされる場合は、この値を common に置き換えます。 "個人用の Microsoft アカウントのみ" にサポートを制限するには、この値を consumers に置き換えます。

MSAL を使用してユーザーのサインインを処理する

JavaScriptSPA フォルダーで、authPopup.js という名前の新しい .js ファイルを作成します。これには、認証とトークン取得ロジックを記述することになります。 次のコードを追加します。

const myMSALObj = new Msal.UserAgentApplication(msalConfig);

function signIn() {
  myMSALObj.loginPopup(loginRequest)
    .then(loginResponse => {
      console.log('id_token acquired at: ' + new Date().toString());
      console.log(loginResponse);

      if (myMSALObj.getAccount()) {
        showWelcomeMessage(myMSALObj.getAccount());
      }
    }).catch(error => {
      console.log(error);
    });
}

function signOut() {
  myMSALObj.logout();
}

function callMSGraph(theUrl, accessToken, callback) {
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.onreadystatechange = function () {
        if (this.readyState == 4 && this.status == 200) {
           callback(JSON.parse(this.responseText));
        }
    }
    xmlHttp.open("GET", theUrl, true); // true for asynchronous
    xmlHttp.setRequestHeader('Authorization', 'Bearer ' + accessToken);
    xmlHttp.send();
}

function getTokenPopup(request) {
  return myMSALObj.acquireTokenSilent(request)
    .catch(error => {
      console.log(error);
      console.log("silent token acquisition fails. acquiring token using popup");

      // fallback to interaction when the silent call fails
        return myMSALObj.acquireTokenPopup(request)
          .then(tokenResponse => {
            return tokenResponse;
          }).catch(error => {
            console.log(error);
          });
    });
}

function seeProfile() {
  if (myMSALObj.getAccount()) {
    getTokenPopup(loginRequest)
      .then(response => {
        callMSGraph(graphConfig.graphMeEndpoint, response.accessToken, updateUI);
        profileButton.classList.add('d-none');
        mailButton.classList.remove('d-none');
      }).catch(error => {
        console.log(error);
      });
  }
}

function readMail() {
  if (myMSALObj.getAccount()) {
    getTokenPopup(tokenRequest)
      .then(response => {
        callMSGraph(graphConfig.graphMailEndpoint, response.accessToken, updateUI);
      }).catch(error => {
        console.log(error);
      });
  }
}

検証にトークンを使用する

ユーザーが初めて [サインイン] ボタンを選択すると、authPopup.js ファイルに追加した signIn 関数が MSAL の loginPopup 関数を呼び出してサインイン プロセスを開始します。 この関数により、ユーザーに資格情報の入力を求めるポップアップ ウィンドウが開きます。

サインインに成功すると、ユーザーは元の index.html ページにリダイレクトされます。 msal.js ファイルが ID トークンを受信して処理し、トークン内の情報がキャッシュされます。 ID トークンには、ユーザーの表示名など、ユーザーに関する基本的な情報が含まれています。 なんらかの目的で、ID トークン内のデータを使用する予定がある場合は、このトークンがアプリケーションの有効なユーザーに対して発行されたことを保証するために、バックエンド サーバーがトークンを検証していることを確認します。

このチュートリアルで作成するアプリでは、acquireTokenSilent および/または acquireTokenPopup を呼び出して、"アクセス トークン" を取得します。 このアプリは、このトークンを使用して、ユーザーのプロファイル情報について Microsoft Graph API に対してクエリを実行します。 ID トークンを検証するサンプルが必要な場合は、Github のサンプル アプリケーションに関するページを参照してください。ここでは、トークンの検証に ASP.NET Web API が使用されています。

ユーザー トークンを対話形式で取得する

最初のサインインの後は、ユーザーがリソースにアクセスするためのトークンを要求するたびに再認証する必要はありません。 ほとんどの場合、このアプリは acquireTokenSilent を使用してトークンを取得します。 ただし、次のような状況では、ユーザーに Microsoft ID プラットフォームとのやり取りを強制する場合があります。

  • パスワードの有効期限が切れているため、ユーザーは資格情報を再入力する必要がある。
  • アプリケーションがリソースへのアクセスを要求し、ユーザーの同意が必要な場合。
  • 2 要素認証が必須である。

acquireTokenPopup を呼び出すと、ポップアップ ウィンドウが表示されます (または、acquireTokenRedirect によってユーザーが Microsoft ID プラットフォームにリダイレクトされます)。 ユーザーはそのウィンドウ内で、自分の資格情報の確認、必要なリソースへの同意、2 要素認証の完了のいずれかの方法で操作を行う必要があります。

ユーザー トークンを自動で取得する

acquireTokenSilent メソッドは、ユーザーの操作なしでトークンの取得や更新を処理します。 loginPopup (または loginRedirect) が初めて実行されると、その後の呼び出しでは、保護されたリソースにアクセスするためのトークンを取得するために acquireTokenSilent が使用されます。 (トークンを要求または更新するための呼び出しは自動的に行われます)。

ユーザーのパスワードの有効期限が切れた場合など、場合によっては acquireTokenSilent メソッドが失敗することがあります。 このアプリケーションでは、この例外を次の 2 つの方法で処理できます。

  • すぐに acquireTokenPopup を呼び出し、ユーザー サインイン プロンプトをトリガーします。 オンライン アプリケーション (ユーザーが使用できる非認証コンテンツが含まれていない) の場合は、一般に、この方法が使用されます。 このチュートリアルで作成するサンプルでは、このパターンを使用します。

  • 対話型サインインが必要であることをユーザーに視覚的に示します。 ユーザーが適切なタイミングを選んでサインインするか、アプリケーションが後で acquireTokenSilent を再試行できます。

    他に中断なく使用できる機能がアプリケーションにある場合は、一般に、この方法が使用されます。 たとえば、使用可能な非認証コンテンツがアプリケーションに含まれている場合が考えられます。 この場合、ユーザーは、保護されたリソースにアクセスしたり、古くなった情報を更新したりするためにサインインするタイミングを決定できます。

注意

このチュートリアルでは、既定で loginPopup および acquireTokenPopup メソッドを使用します。 ブラウザーとして Internet Explorer を使用している場合は、Internet Explorer がポップアップ ウィンドウを処理する方法に伴う既知の問題があるため、loginRedirect および acquireTokenRedirect メソッドを使用することをお勧めします。

"リダイレクト メソッド" を使用して同じ結果を得る方法については、サンプル コードに関するページを参照してください。

取得したトークンを使用して Microsoft Graph API を呼び出す

  1. JavaScriptSPA フォルダーに、graphConfig.js という名前の .js ファイルを作成します。これには、Representational State Transfer (REST) エンドポイントを格納します。 次のコードを追加します。

       const graphConfig = {
         graphMeEndpoint: "Enter_the_Graph_Endpoint_Here/v1.0/me",
         graphMailEndpoint: "Enter_the_Graph_Endpoint_Here/v1.0/me/messages"
       };
    

    Enter_the_Graph_Endpoint_Here は Microsoft Graph API のインスタンスです。 グローバル Microsoft Graph API エンドポイントの場合、これを https://graph.microsoft.com に置き換えることができます。 国内クラウド デプロイの場合は、Graph API のドキュメントに関するページを参照してください。

  2. graph.js という名前のファイルを作成します。これには、Microsoft Graph API に対する REST 呼び出しを記述することになります。 それにより、SPA は、処理なしで簡単かつ柔軟な方法で Web サービスにアクセスできるようになります。 次のコードを追加します。

    function callMSGraph(endpoint, token, callback) {
      const headers = new Headers();
      const bearer = `Bearer ${token}`;
    
      headers.append("Authorization", bearer);
    
      const options = {
          method: "GET",
          headers: headers
      };
    
      console.log('request made to Graph API at: ' + new Date().toString());
    
      fetch(endpoint, options)
        .then(response => response.json())
        .then(response => callback(response, endpoint))
        .catch(error => console.log(error))
    }
    

保護された API に対する REST 呼び出しについての詳細

このチュートリアルで作成するサンプル アプリケーションでは、callMSGraph() メソッドを使用して、トークンが必要な保護されたリソースに対して HTTP GET 要求を実行します。 その後、この要求からその内容が呼び出し元に返されます。

このメソッドは、取得したトークンを HTTP Authorization ヘッダーに追加します。 このサンプル アプリケーションの場合、リソースは、ユーザーのプロファイル情報を表示する Microsoft Graph API me エンドポイントです。

コードのテスト

コードを設定したので、それをテストする必要があります。

  1. index.html ファイルの場所に基づく TCP ポートをリッスンするように、サーバーを構成します。 Node.js の場合は、Web サーバーを起動して、前に指定したポートをリッスンできます。 JavaScriptSPA フォルダーからコマンドライン プロンプトで次のコマンドを実行します。

    npm install
    npm start
    
  2. ブラウザーで、「http://localhost:3000」と入力します。 index.html ファイルの内容と、画面の右上に [サインイン] ボタンが表示されます。

重要

ブラウザーの設定で、必ずサイトのポップアップとリダイレクトを有効にしてください。

ブラウザーに index.html ファイルが読み込まれたら、 [サインイン] を選択します。 Microsoft ID プラットフォームにサインインするように求められます。

JavaScript SPA アカウントのサインイン ウィンドウを示すスクリーンショット。

アプリケーションへの初回サインイン時には、お使いのプロファイルへのアクセスを許可してサインインすることを求められます。 [同意する] を選択して続行します。

アプリがアクセス許可を要求するウィンドウを示すスクリーンショット。

アプリケーションの結果を表示する

サインインすると、表示名の下にある [詳細] を選択できます。 ユーザー プロファイル情報は、表示された Microsoft Graph API 応答で返されます。

Microsoft Graph API 呼び出しから予想される結果を示すスクリーンショット。

スコープと委任されたアクセス許可の詳細

Microsoft Graph API は、ユーザーのプロファイルを読み込むためにスコープ User.Read を必要とします。 このスコープは既定で、登録ポータルに登録されているすべてのアプリケーションで自動的に追加されます。 Microsoft Graph の他の API や、バックエンド サーバーのカスタム API には、追加のスコープが必要な場合があります。 たとえば、Microsoft Graph API には、ユーザーのメールを表示するための Mail.Read スコープが必要です。

注意

スコープの数を増やすと、ユーザーは追加の同意を求められることがあります。

ヘルプとサポート

サポートが必要な場合、問題をレポートする場合、またはサポート オプションについて知りたい場合は、開発者向けのヘルプとサポートに関するページを参照してください。

次のステップ

シナリオ シリーズの最初の部分で、Microsoft ID プラットフォームの SPA 開発についてさらに深く掘り下げます。