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

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

Microsoft Entra IDでは、ユーザーが初めて認証するときにセッション Cookie を設定することで SSO を有効にします。 MSAL.js では、アプリケーション ドメインごとにブラウザー ストレージにユーザーの ID トークンとアクセス トークンもキャッシュされます。 セッション Cookie と Microsoft Authentication Library (MSAL) キャッシュMicrosoft Entra 2 つのメカニズムは互いに独立していますが、連携して 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 ID とのセッションで複数のユーザー アカウントを持っている場合は、サインインするアカウントを選択するように求められます。 そのため、 ssoSilent 方法を使用して SSO を実現するには、2 つの方法があります。

ユーザーヒント付き

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

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

ログイン ヒントの使用

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 が含まれています。これは、対話型トークン要求時にヒントとして使用されます。 アプリケーション間でヒントを渡して、アプリケーション A がユーザーのサインイン、loginHintの読み取り、アプリケーション B への要求と現在のテナント コンテキストの送信を容易にするサイレント SSO を容易にすることができます。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
    }
}

ユーザー ヒントなし

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

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)

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

  • アプリケーション ユーザーがポップアップ メソッドとサイレント メソッドのみを使用する場合は、redirectUri構成オブジェクトにPublicClientApplicationを設定します。
  • アプリケーションでリダイレクト メソッドも使用する場合は、要求ごとに 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要求でログイン プロンプト パラメーターを使用できます。 詳細については、 プロンプトの動作MSAL.js 参照してください。

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

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


// 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 の詳細については、以下を参照してください。