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

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

Azure Active Directory (Azure AD) では、ユーザーが初めて認証を行ったときに、セッション Cookie を設定することで SSO が有効になります。 MSAL.js を使うと、1 つまたは複数のアプリケーション用に開かれたブラウザー タブの間での SSO にセッション Cookie を使用できます。

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

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

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

const msalInstance = new msal.PublicClientApplication(config);

異なるアプリ間の SSO

ユーザーが認証を行うと、ブラウザーの Azure AD ドメインでセッション Cookie が設定されます。 MSAL.js では、このセッション Cookie に依存して、ユーザーに異なるアプリケーション間の SSO が提供されます。 また、MSAL.js では、アプリケーション ドメインごとに、ユーザーの ID トークンとアクセス トークンがブラウザーのストレージにキャッシュされます。

MSAL.js では、ユーザーをサインインさせ、対話なしでトークンを取得する ssoSilent メソッドを提供します。 ただし、ユーザーが Azure AD とのセッションに複数のユーザー アカウントを持っている場合、ユーザーはサインインするアカウントの選択を求められます。 そのため、ssoSilent メソッドを使用して SSO を行うには 2 つの方法があります。

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

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

  • セッション ID sid (account オブジェクトの idTokenClaims から取得できます)
  • login_hint (account オブジェクトのユーザー名プロパティまたは ID トークンの upn 要求から取得できます)
  • account (アカウント メソッドを 1 つ使用して取得できます)

セッション ID の使用

セッション ID を使用するには、オプションの要求として sid をアプリの ID トークンに追加します。 sid 要求により、アプリケーションは、ユーザーのアカウント名やユーザー名とは関係なく、ユーザーの Azure AD セッションを識別できます。 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
    }
}

ログイン ヒントの使用

対話型認証要求の間に通常表示されるアカウント選択プロンプトをバイパスするには (または、オプションの要求 sid を構成していないサイレント要求の場合は)、loginHint を指定します。 マルチテナント アプリケーションでは、domain_hint も含めます。

const request = {
  scopes: ["user.read"],
  loginHint: preferred_username,
  extraQueryParameters: { domain_hint: "organizations" },
};

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
    }
}

loginHintdomain_hint の値は、ユーザーの ID トークンから取得します。

  • loginHint: ID トークンの preferred_username 要求の値を使います。

  • domain_hint: ID トークンの tid 要求の値を使います。 /common 機関を使用するマルチテナント アプリケーションによって行われる要求で必要です。 他のアプリケーションの場合は省略可能です。

ログイン ヒントとドメイン ヒントについて詳しくは、「Microsoft ID プラットフォームと OAuth 2.0 承認コード フロー」をご覧ください。

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

ユーザー アカウント情報を把握している場合は、次の 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 を開き、Azure AD との既存のセッションを再利用しようとします。 これは、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() を使用して対話型認証要求を作成する必要があります。

また、サイレント メソッドを使用する場合は、要求オブジェクトが必要になります。 ユーザーのサインイン情報が既にある場合は、loginHint または sid のどちらかの省略可能なパラメーターを渡して、特定のアカウントにサインインすることができます。

MSAL.js の更新に対する ADAL.js での SSO

MSAL.js には、Azure AD の認証シナリオに対する ADAL.js での機能パリティがあります。 ADAL.js から MSAL.js への移行を容易にし、ユーザーにサインインを繰り返し要求しなくて済むように、ライブラリは ADAL.js キャッシュ内にあるユーザーのセッションを表す ID トークンを読み取り、ユーザーを MSAL.js にシームレスにサインインさせます。

ADAL.js から更新するときに SSO の動作を利用するには、ライブラリでトークンのキャッシュ用に 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);

cacheLocation が構成されると、MSAL.js では ADAL.js で認証されたユーザーのキャッシュされた状態を読み取って、MSAL.js で SSO を提供するために使用することができます。

次の手順

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