使用 MSAL.js 進行單一登入

單一登錄 (SSO) 可藉由減少使用者要求認證次數來提供更順暢的體驗。 使用者一次輸入其認證,而已建立的會話可由相同裝置上的其他應用程式重複使用,而不會進一步提示。

當使用者第一次驗證時,Microsoft Entra ID 會藉由設定會話 Cookie 來啟用 SSO。 MSAL.js也會在每個應用程式網域的瀏覽器記憶體中快取使用者的標識元令牌和存取令牌。 這兩個機制:Microsoft Entra 會話 Cookie 和 Microsoft 驗證連結庫 (MSAL) 快取彼此獨立,但共同運作以提供 SSO 行為。

相同應用程式的瀏覽器索引標籤之間的 SSO

當用戶在數個索引標籤中開啟應用程式並登入其中一個時,可以在其他索引卷標上登入相同的應用程式,而不會提示。 若要這樣做,您必須在 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 ID 的會話中有多個用戶帳戶,則會提示他們挑選要登入的帳戶。 因此,有兩種方式可以使用 方法來達成 SSO ssoSilent

使用使用者提示

若要改善效能並確保授權伺服器會尋找正確的帳戶會話,您可以在方法的要求對象 ssoSilent 中傳遞下列其中一個選項,以無訊息方式取得令牌。

我們建議使用login_hint提供的ssoSilentloginHint選擇性標識符令牌宣告,因為它是無訊息和互動式要求最可靠的帳戶提示。

使用登入提示

login_hint選擇性宣告會針對嘗試登入的用戶帳戶,提供 Microsoft Entra 識別碼的提示。 若要略過通常會在互動式驗證要求期間顯示的帳戶選取提示,請提供 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 資訊不符合任何現有的使用者,則會將其重新導向,以完成標準登入體驗,包括帳戶選取。

使用會話標識碼

若要使用會話標識碼,請將 新增 sid應用程式識別碼令牌的選擇性宣告 。 宣告 sid 可讓應用程式識別使用者的 Microsoft Entra 工作階段,與其帳戶名稱或使用者名稱無關。 若要瞭解如何新增之類的 sid選擇性宣告,請參閱 將選擇性宣告提供給您的應用程式。 在您在 ssoSilent MSAL.js 中使用無訊息驗證要求中的會話識別碼 (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
    }
}

沒有使用者提示

您可以嘗試使用 ssoSilent 方法,而不傳遞任何account、 或 login_hintsid如下列程式代碼所示:

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.

錯誤表示伺服器無法判斷要登入的帳戶,而且需要上一個範例中的其中一個參數(accountlogin_hintsid) 或互動式登入來選擇帳戶。

使用時的考慮 ssoSilent

重新導向 URI (回復 URL)

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

  • 如果應用程式使用者只有快顯和無訊息方法,請在組態物件上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

若要解決錯誤,用戶必須使用 或 loginRedirect()建立互動式驗證要求loginPopup()。 在某些情況下,無提示值可以與互動式MSAL.js方法來達成 SSO。 如需詳細資訊,請參閱 具有 prompt=none 的互動式要求。 如果您已經有使用者的登入資訊,您可以傳遞 loginHintsid 選擇性參數來登入特定帳戶。

以 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快取中的用戶會話。 若要在從 ADAL.js 移轉時利用這項功能,您必須確保連結庫用於 localStorage 快取令牌。 cacheLocation在初始化MSAL.js和ADAL.js組態中,將 設定為 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 的詳細資訊,請參閱: