使用 MSAL.js 進行單一登入

單一登入(SSO)透過減少使用者被要求提供憑證的次數,提供更無縫的體驗。 使用者只需輸入一次憑證,建立的會話即可在同一裝置上被其他應用程式重複使用,無需進一步提示。

Microsoft Entra ID 透過設定使用者首次驗證時的會話 Cookie 來啟用 SSO。 MSAL.js 也會依各應用程式網域,將使用者的 ID 權杖和存取權杖快取在瀏覽器儲存體中。 這兩個機制,Microsoft Entra 會話 cookie 與 Microsoft 驗證資源庫(MSAL)快取,彼此獨立,但協同運作以提供 SSO 行為。

同一個應用程式的瀏覽器分頁間的單一登入

當使用者在多個分頁開啟應用程式並在其中一個分頁登入時,他們可以在其他分頁開啟同一應用程式時,無需被提示登入。 為此,你需要在 MSAL.js 設定物件中設定 cacheLocationlocalStorage 如下範例所示:

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

const msalInstance = new msal.PublicClientApplication(config);

此時,不同瀏覽器分頁中的應用程式實例會使用相同的 MSAL 快取,因此彼此共享認證狀態。 你也可以利用 MSAL 事件來更新使用者從其他瀏覽器分頁或視窗登入時的應用程式實例。 更多資訊請參見:跨 分頁與視窗同步登入狀態

不同應用程式之間的單一登入

當使用者通過驗證時,系統會在瀏覽器中的 Microsoft Entra 網域上設定一個工作階段 Cookie。 MSAL.js 依賴此工作階段 Cookie,為使用者在不同應用程式之間提供單一登入(SSO)。 特別是,MSAL.js 提供 ssoSilent 一種無需互動即可登入用戶並取得代幣的方法。 然而,如果使用者在使用 Microsoft Entra ID 的會話中有多個使用者帳號,系統會提示他們選擇一個帳號來登入。 因此,使用 ssoSilent 方法達成單向 SSO 有兩種方法。

附有使用者提示

為了提升效能並確保授權伺服器會尋找正確的帳號會話,你可以在方法的 ssoSilent 請求物件中傳遞以下選項之一,靜默取得該令牌。

我們建議使用login_hint提供給 ssoSilent 的選用 ID 權杖宣告作為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,其會在互動式權杖請求期間作為提示使用。 提示可以在應用程式間傳遞,以促進靜默 SSO,應用程式 A 可以登入使用者、讀取 loginHint,然後將申訴及當前租戶上下文傳送給應用程式 B。Microsoft Entra ID 會嘗試預先填寫登入表單,或繞過帳號選擇提示,直接對指定使用者進行認證程序。

如果申訴中的 login_hint 資訊與任何現有使用者不符,他們會被導向進入標準登入體驗,包括帳號選擇。

使用 session ID

要使用 session ID,請在應用程式的 ID 標記中新增 sid選的聲明 。 該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() or 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
    }
}

無需使用者提示

你可以嘗試使用 ssoSilent 此方法而不傳遞任何 accountsidlogin_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
    }
}

然而,如果應用程式在同一個瀏覽器會話中有多個使用者,或該使用者在該瀏覽器會話中有多個帳號,就有可能發生靜默登入錯誤。 若多個帳號可用,可能會顯示以下錯誤:

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(回覆網址)

為了提升效能並避免問題,可以設定 redirectUri 為空白頁面或其他不使用 MSAL 的頁面。

  • 如果應用程式只使用快顯和靜默方法,請在 PublicClientApplication 設定物件上設定 redirectUri
  • 如果應用程式也使用重新導向方法,請針對每個要求分別設定 redirectUri

第三方 Cookie

ssoSilent嘗試開啟隱藏的 iframe 並重用現有的 Microsoft Entra ID 會話。 這在阻擋第三方 Cookie 的瀏覽器(如 Safari)中無法運作,且會導致互動錯誤:

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 的互動式請求。 如果你已經有該使用者的登入資訊,你可以傳遞 loginHintsid 這兩個選用參數之一,以登入特定帳戶。

使用 prompt=login 停用 SSO

如果你希望 Microsoft Entra ID 即使在與授權伺服器已有作用中工作階段時,仍提示使用者輸入其憑證,則可以在使用 MSAL.js 的要求中使用 login 提示參數。 詳情請參見 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的資訊,請參閱: