MSAL.js でのシングル サインオン

シングル サインオン (SSO) を使用すると、ユーザーが資格情報の入力を求められる回数が減り、よりシームレスなエクスペリエンスが提供されます。 ユーザーが資格情報を 1 回入力すると、それ以上プロンプトは表示されず、確立されたセッションを同じデバイス上の他のアプリケーションで再利用できます。

Microsoft Entra ID では、ユーザーが初めて認証を行ったときに、セッション Cookie を設定することで SSO が有効になります。 また、MSAL.js では、アプリケーション ドメインごとに、ユーザーの ID トークンとアクセス トークンがブラウザーのストレージにキャッシュされます。 2 つのメカニズム (Microsoft Entra セッション Cookie と Microsoft Authentication Library (MSAL) キャッシュ) は相互に独立していますが、連携して SSO の動作を提供します。

同じアプリのブラウザー タブ間の SSO

ユーザーが複数のタブでアプリケーションを開き、そのうちの 1 つにサインインすると、他のタブで開かれている同じアプリにも、プロンプトなしでサインインできます。 これを行うには、次の例で示すように、MSAL.js 構成オブジェクトの cacheLocationlocalStorage に設定する必要があります:

const config = {
  auth: {
    clientId: "1111-2222-3333-4444-55555555",
  },
  cache: {
    cacheLocation: "localStorage",
  },
};

const msalInstance = new msal.PublicClientApplication(config);

この場合、異なるブラウザー タブのアプリケーション インスタンスが同じ MSAL キャッシュを使うため、それらの間で認証状態が共有されます。 MSAL イベントを使って、ユーザーが別のブラウザー タブまたはウィンドウからログインしたときに、アプリケーション インスタンスを更新することもできます。 詳しくは、「タブ間およびウィンドウ間でのログイン状態の同期」をご覧ください

異なるアプリ間の SSO

ユーザーが認証を行うと、ブラウザーの Microsoft Entra ドメインでセッション Cookie が設定されます。 MSAL.js では、このセッション Cookie に依存して、ユーザーに異なるアプリケーション間の SSO が提供されます。 具体的には、MSAL.js では、対話なしでのユーザーのサインインとトークンの取得のための ssoSilent メソッドが提供されています。 ただし、ユーザーが Microsoft Entra とのセッションに複数のユーザー アカウントを持っている場合は、サインインするアカウントの選択を求められます。 そのため、ssoSilent メソッドを使用して SSO を行うには 2 つの方法があります。

ユーザー ヒントを使用する

パフォーマンスを向上させ、承認サーバーが正しいアカウント セッションを探すようにするには、ssoSilent メソッドの要求オブジェクトで次のいずれかのオプションを渡して、トークンをサイレントで取得できます。

サイレント要求と対話型要求の最も信頼性の高いアカウント ヒントであるため、loginHint として ssoSilent に提供されるlogin_hintオプションの ID トークン要求を使用することをお勧めします。

ログイン ヒントの使用

オプションの要求 login_hint は、サインインを試みるユーザー アカウントに関するヒントを Microsoft Entra ID に提供します。 対話型認証要求時に通常表示されるアカウント選択プロンプトをバイパスするには、次のように loginHint を指定します:

const silentRequest = {
    scopes: ["User.Read", "Mail.Read"],
    loginHint: "user@contoso.com"
};

try {
    const loginResponse = await msalInstance.ssoSilent(silentRequest);
} catch (err) {
    if (err instanceof InteractionRequiredAuthError) {
        const loginResponse = await msalInstance.loginPopup(silentRequest).catch(error => {
            // handle error
        });
    } else {
        // handle error
    }
}

この例では、loginHint には、対話型トークン要求時にヒントとして使用されるユーザーの電子メールまたは UPN が含まれています。 アプリケーション間でヒントを渡して、サイレント SSO を容易にできます。アプリケーション A は、ユーザーをサインインさせ、loginHint を読み取り、アプリケーション B に要求と現在のテナント コンテキストを送信できます。Microsoft Entra ID は、サインイン フォームの事前入力またはアカウント選択プロンプトのバイパスを試み、指定されたユーザーの認証プロセスを直接続行します。

login_hint 要求内の情報が既存のユーザーと一致しない場合は、アカウントの選択など、標準のサインイン エクスペリエンスを行うようにリダイレクトされます。

セッション ID の使用

セッション ID を使用するには、オプションの要求として sid をアプリの ID トークンに追加します。 sid 要求により、アプリケーションは、ユーザーのアカウント名やユーザー名とは関係なく、ユーザーの Microsoft Entra セッションを識別できます。 sid のようなオプションの要求を追加する方法については、「アプリに省略可能な要求を提供する」をご覧ください。 MSAL.js で ssoSilent を使って行うサイレント認証要求で、セッション ID (SID) を使用します。

const request = {
  scopes: ["user.read"],
  sid: sid,
};

 try {
    const loginResponse = await msalInstance.ssoSilent(request);
} catch (err) {
    if (err instanceof InteractionRequiredAuthError) {
        const loginResponse = await msalInstance.loginPopup(request).catch(error => {
            // handle error
        });
    } else {
        // handle error
    }
}

アカウント オブジェクトの使用

ユーザー アカウント情報を把握している場合は、次の getAccountByUsername() または getAccountByHomeId() メソッドを使用してユーザー アカウントを取得することもできます。

const username = "test@contoso.com";
const myAccount  = msalInstance.getAccountByUsername(username);

const request = {
    scopes: ["User.Read"],
    account: myAccount
};

try {
    const loginResponse = await msalInstance.ssoSilent(request);
} catch (err) {
    if (err instanceof InteractionRequiredAuthError) {
        const loginResponse = await msalInstance.loginPopup(request).catch(error => {
            // handle error
        });
    } else {
        // handle error
    }
}

ユーザー ヒントを使用しない

以下のコードに示すように、accountsid、または login_hint を渡さずに、ssoSilent メソッドの使用を試みることができます。

const request = {
    scopes: ["User.Read"]
};

try {
    const loginResponse = await msalInstance.ssoSilent(request);
} catch (err) {
    if (err instanceof InteractionRequiredAuthError) {
        const loginResponse = await msalInstance.loginPopup(request).catch(error => {
            // handle error
        });
    } else {
        // handle error
    }
}

ただし、アプリケーションの 1 つのブラウザー セッションに複数のユーザーがいる場合、またはユーザーがその 1 つのブラウザー セッションに対して複数のアカウントを持っている場合は、サイレント サインイン エラーが発生する可能性があります。 複数のアカウントが使用可能な場合は、次のエラーが表示されることがあります。

InteractionRequiredAuthError: interaction_required: AADSTS16000: Either multiple user identities are available for the current request or selected account is not supported for the scenario.

このエラーは、どのアカウントにサインインするかをサーバーが判断できなかったことを示しており、アカウントを選択するには、前の例のパラメーター (accountlogin_hintsid) のいずれか、または対話型サインインが必要になります。

ssoSilent を使用する場合の考慮事項

リダイレクト URI (応答 URL)

パフォーマンスを向上させ、問題を回避するには、空白ページ、または MSAL を使用しない他のページに redirectUri を設定します。

  • アプリケーションでポップアップ メソッドとサイレント メソッドのみを使用する場合は、PublicClientApplication 構成オブジェクトに redirectUri を設定します。
  • アプリケーションでリダイレクト メソッドも使用する場合は、要求ごとに redirectUri を設定します。

サード パーティの Cookie

ssoSilent は、非表示の iframe を開き、Microsoft Entra ID との既存のセッションを再利用しようとします。 これは、Safari などのサードパーティの Cookie をブロックするブラウザーでは機能せず、対話エラーが発生します。

InteractionRequiredAuthError: login_required: AADSTS50058: A silent sign-in request was sent but no user is signed in. The cookies used to represent the user's session were not sent in the request to Azure AD

このエラーを解決するために、ユーザーは loginPopup() または loginRedirect() を使用して対話型認証要求を作成する必要があります。 場合によっては、プロンプト値 none を対話型の MSAL.js メソッドと共に使って、SSO を実現できます。 詳しくは、「prompt=none の対話型要求」をご覧ください。 ユーザーのサインイン情報が既にある場合は、loginHint または sid のどちらかの省略可能なパラメーターを渡して、特定のアカウントにサインインすることができます。

prompt=login での SSO の否定

認可サーバーとのアクティブなセッションがあるにもかかわらず、Microsoft Entra ID でユーザーに資格情報の入力を求めたい場合は、MSAL.js の要求で login プロンプト パラメーターを使用できます。 詳しくは、MSAL.js プロンプトの動作に関する記事をご覧ください。

ADAL.js と MSAL.js の間での認証状態の共有

MSAL.js には、Microsoft Entra ID の認証シナリオに対する ADAL.js での機能パリティがあります。 ADAL.js から MSAL.js への移行を容易にし、アプリ間で認証状態を共有するために、ライブラリは、ADAL.js キャッシュ内のユーザーのセッションを表す ID トークンを読み取ります。 ADAL.js から移行するときにこれを利用するには、ライブラリでトークンのキャッシュに localStorage を使っていることを確認する必要があります。 次のように、初期化時に、MSAL.js と ADAL.js 両方の構成で、cacheLocationlocalStorage に設定します。


// In ADAL.js
window.config = {
  clientId: "1111-2222-3333-4444-55555555",
  cacheLocation: "localStorage",
};

var authContext = new AuthenticationContext(config);

// In latest MSAL.js version
const config = {
  auth: {
    clientId: "1111-2222-3333-4444-55555555",
  },
  cache: {
    cacheLocation: "localStorage",
  },
};

const msalInstance = new msal.PublicClientApplication(config);

次の手順

SSO について詳しくは、以下をご覧ください。