次の方法で共有


チュートリアル: JavaScript シングルページ アプリ (SPA) からサインインしてサインアウトする

適用対象: 白いチェック マークが付いた緑色の円。 従業員テナント緑 の円と白いチェック マーク記号。 外部テナント (詳細)

このチュートリアルは、JavaScript シングルページ アプリケーション (SPA) の構築と、Microsoft ID プラットフォームを使用した認証の準備を行うシリーズの最後の部分です。 このシリーズのパート 2 では、JavaScript SPA に認証フローを追加し、応答性の高い UI を構築しました。 この最後の手順では、アプリでサインインとサインアウトの機能をテストする方法について説明します。

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

  • claimUtils.js ファイルにコードを追加して要求テーブルを作成する
  • アプリのサインインとサインアウト
  • ID トークンから返された要求を表示する

前提条件

claimUtils.js ファイルにコードを追加する (省略可能)

ID トークンから返された要求を表示できるテーブルの機能を追加するには 、claimUtils.jsファイル にコードを追加します。 このコード スニペットは、要求テーブルに適切な説明と対応する値を設定します。

  1. パブリック/claimUtils.js を開き、次のコード スニペットを追加します。

     /**
     * Populate claims table with appropriate description
     * @param {Object} claims ID token claims
     * @returns claimsObject
     */
    const createClaimsTable = (claims) => {
        let claimsObj = {};
        let index = 0;
    
        Object.keys(claims).forEach((key) => {
            if (typeof claims[key] !== 'string' && typeof claims[key] !== 'number') return;
            switch (key) {
                case 'aud':
                    populateClaim(
                        key,
                        claims[key],
                        "Identifies the intended recipient of the token. In ID tokens, the audience is your app's Application ID, assigned to your app in the Entra admin center.",
                        index,
                        claimsObj
                    );
                    index++;
                    break;
                case 'iss':
                    populateClaim(
                        key,
                        claims[key],
                        'Identifies the issuer, or authorization server that constructs and returns the token. It also identifies the Microsoft Entra tenant for which the user was authenticated. If the token was issued by the v2.0 endpoint, the URI will end in /v2.0. The GUID that indicates that the user is a consumer user from a Microsoft account is 9188040d-6c67-4c5b-b112-36a304b66dad.',
                        index,
                        claimsObj
                    );
                    index++;
                    break;
                case 'iat':
                    populateClaim(
                        key,
                        changeDateFormat(claims[key]),
                        'Issued At indicates when the authentication for this token occurred.',
                        index,
                        claimsObj
                    );
                    index++;
                    break;
                case 'nbf':
                    populateClaim(
                        key,
                        changeDateFormat(claims[key]),
                        'The nbf (not before) claim identifies the time (as UNIX timestamp) before which the JWT must not be accepted for processing.',
                        index,
                        claimsObj
                    );
                    index++;
                    break;
                case 'exp':
                    populateClaim(
                        key,
                        changeDateFormat(claims[key]),
                        "The exp (expiration time) claim identifies the expiration time (as UNIX timestamp) on or after which the JWT must not be accepted for processing. It's important to note that in certain circumstances, a resource may reject the token before this time. For example, if a change in authentication is required or a token revocation has been detected.",
                        index,
                        claimsObj
                    );
                    index++;
                    break;
                case 'name':
                    populateClaim(
                        key,
                        claims[key],
                        "The principal about which the token asserts information, such as the user of an application. This value is immutable and can't be reassigned or reused. It can be used to perform authorization checks safely, such as when the token is used to access a resource. By default, the subject claim is populated with the object ID of the user in the directory",
                        index,
                        claimsObj
                    );
                    index++;
                    break;
                case 'preferred_username':
                    populateClaim(
                        key,
                        claims[key],
                        'The primary username that represents the user. It could be an email address, phone number, or a generic username without a specified format. Its value is mutable and might change over time. Since it is mutable, this value must not be used to make authorization decisions. It can be used for username hints, however, and in human-readable UI as a username. The profile scope is required in order to receive this claim.',
                        index,
                        claimsObj
                    );
                    index++;
                    break;
                case 'nonce':
                    populateClaim(
                        key,
                        claims[key],
                        'The nonce matches the parameter included in the original /authorize request to the IDP. If it does not match, your application should reject the token.',
                        index,
                        claimsObj
                    );
                    index++;
                    break;
                case 'oid':
                    populateClaim(
                        key,
                        claims[key],
                        'The oid (user’s object id) is the only claim that should be used to uniquely identify a user in an Azure AD tenant. The token might have one or more of the following claim, that might seem like a unique identifier, but is not and should not be used as such.',
                        index,
                        claimsObj
                    );
                    index++;
                    break;
                case 'tid':
                    populateClaim(
                        key,
                        claims[key],
                        'The tenant ID. You will use this claim to ensure that only users from the current Azure AD tenant can access this app.',
                        index,
                        claimsObj
                    );
                    index++;
                    break;
                case 'upn':
                    populateClaim(
                        key,
                        claims[key],
                        '(user principal name) – might be unique amongst the active set of users in a tenant but tend to get reassigned to new employees as employees leave the organization and others take their place or might change to reflect a personal change like marriage.',
                        index,
                        claimsObj
                    );
                    index++;
                    break;
                case 'email':
                    populateClaim(
                        key,
                        claims[key],
                        'Email might be unique amongst the active set of users in a tenant but tend to get reassigned to new employees as employees leave the organization and others take their place.',
                        index,
                        claimsObj
                    );
                    index++;
                    break;
                case 'acct':
                    populateClaim(
                        key,
                        claims[key],
                        'Available as an optional claim, it lets you know what the type of user (homed, guest) is. For example, for an individual’s access to their data you might not care for this claim, but you would use this along with tenant id (tid) to control access to say a company-wide dashboard to just employees (homed users) and not contractors (guest users).',
                        index,
                        claimsObj
                    );
                    index++;
                    break;
                case 'sid':
                    populateClaim(key, claims[key], 'Session ID, used for per-session user sign-out.', index, claimsObj);
                    index++;
                    break;
                case 'sub':
                    populateClaim(
                        key,
                        claims[key],
                        'The sub claim is a pairwise identifier - it is unique to a particular application ID. If a single user signs into two different apps using two different client IDs, those apps will receive two different values for the subject claim.',
                        index,
                        claimsObj
                    );
                    index++;
                    break;
                case 'ver':
                    populateClaim(
                        key,
                        claims[key],
                        'Version of the token issued by the Microsoft identity platform',
                        index,
                        claimsObj
                    );
                    index++;
                    break;
                case 'auth_time':
                    populateClaim(
                        key,
                        claims[key],
                        'The time at which a user last entered credentials, represented in epoch time. There is no discrimination between that authentication being a fresh sign-in, a single sign-on (SSO) session, or another sign-in type.',
                        index,
                        claimsObj
                    );
                    index++;
                    break;
                case 'at_hash':
                    populateClaim(
                        key,
                        claims[key],
                        'An access token hash included in an ID token only when the token is issued together with an OAuth 2.0 access token. An access token hash can be used to validate the authenticity of an access token',
                        index,
                        claimsObj
                    );
                    index++;
                    break;
                case 'uti':
                case 'rh':
                    index++;
                    break;
                default:
                    populateClaim(key, claims[key], '', index, claimsObj);
                    index++;
            }
        });
    
        return claimsObj;
    };
    
        /**
         * Populates claim, description, and value into an claimsObject
         * @param {string} claim
         * @param {string} value
         * @param {string} description
         * @param {number} index
         * @param {Object} claimsObject
         */
        const populateClaim = (claim, value, description, index, claimsObject) => {
            let claimsArray = [];
            claimsArray[0] = claim;
            claimsArray[1] = value;
            claimsArray[2] = description;
            claimsObject[index] = claimsArray;
        };
    
        /**
         * Transforms Unix timestamp to date and returns a string value of that date
         * @param {string} date Unix timestamp
         * @returns
         */
        const changeDateFormat = (date) => {
            let dateObj = new Date(date * 1000);
            return `${date} - [${dateObj.toString()}]`;
    };
    
  2. ファイルを保存します。

プロジェクトを実行してサインインする

必要なコード スニペットがすべて追加されたため、アプリケーションを Web ブラウザーで呼び出してテストできます。

  1. 新しいターミナルを開き、次のコマンドを実行して Express Web サーバーを起動します。

    npm start
    
  2. ターミナルに表示される http URL (http://localhost:3000など) をコピーし、ブラウザーに貼り付けます。 プライベートまたはシークレット のブラウザー セッションを使用することをお勧めします。

  3. テナントに登録されているアカウントでサインインします。

  4. 次のスクリーンショットのようなインターフェイスが表示され、アプリケーションにサインインしたことを示します。 要求テーブルを追加した場合は、ID トークンから返された要求を表示できます。

    API 呼び出しの結果を示す JavaScript アプリのスクリーンショット。

アプリケーションからサインアウトする

  1. ページの [サインアウト ] ボタンを見つけて選択します。
  2. サインアウト元のアカウントを選択するように求められます。 サインインに使用したアカウントを選択します。

サインアウトしたことを示すメッセージが表示されます。ブラウザー ウィンドウを閉じることができるようになりました。