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 構成オブジェクトの cacheLocation を localStorage
に設定する必要があります:
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
メソッドの要求オブジェクトで次のいずれかのオプションを渡して、トークンをサイレントで取得できます。
login_hint
はaccount
オブジェクトのユーザー名プロパティまたは ID トークンのupn
要求から取得できます。 アプリが B2C でユーザー認証を行っている場合、「ID トークンでユーザー名を放出するために B2C ユーザー フローを構成する」を参照してください- セッション ID
sid
はaccount
オブジェクトのidTokenClaims
から取得できます。 account
は アカウント メソッド を 1 つ使用して取得できます
サイレント要求と対話型要求の最も信頼性の高いアカウント ヒントであるため、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
}
}
ユーザー ヒントを使用しない
以下のコードに示すように、account
、sid
、または 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.
このエラーは、どのアカウントにサインインするかをサーバーが判断できなかったことを示しており、アカウントを選択するには、前の例のパラメーター (account
、login_hint
、sid
) のいずれか、または対話型サインインが必要になります。
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 両方の構成で、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 について詳しくは、以下をご覧ください。