使用 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 的工作階段中有多個使用者帳戶,則系統會提示使用者挑選用以登入的帳戶。 因此,有兩種方法可以使用 ssoSilent
方法實現 SSO。
使用使用者提示
若要改善效能,並確保授權伺服器會尋找正確的帳戶工作階段,您可以在 ssoSilent
方法的要求物件中傳遞以下選項之一,以無訊息方式獲取權杖。
login_hint
(可以從識別碼權仗中的account
物件使用者名稱屬性或upn
宣告中擷取)。 如果您的應用程式使用 B2C 驗證使用者,請參閱:設定 B2C 使用者流程以在識別碼權杖中發出使用者名稱- 工作階段識別碼
sid
(可從account
物件的idTokenClaims
擷取)。 account
(可以使用帳戶方法之一擷取)
我們建議使用login_hint
提供的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,這在互動式權杖要求期間會作為提示。 您可以在應用程式之間傳遞提示,以促進無訊息 SSO,其中應用程式 A 可以登入使用者、讀取 loginHint
,然後將宣告和目前的租用戶內容傳送至應用程式 B。Microsoft Entra ID 會嘗試預先填入登入表格,或略過帳戶選取提示,然後直接繼續進行指定使用者的驗證流程。
如果 login_hint
宣告中的資訊不符合任何現有的使用者,系統會將其重新導向,以完成標準登入體驗,包括帳戶選取。
使用工作階段識別碼
若要使用工作階段識別碼,請將 sid
新增為應用程式識別碼權杖的選擇性宣告。 sid
宣告會允許應用程式識別使用者的 Microsoft Entra 工作階段,而不受其的帳戶名稱或使用者名稱影響。 若要瞭解如何新增和 sid
一樣的選擇性宣告,請參閱做法:為您的應用程式提供選擇性宣告。 在您於 MSAL.js 中對 ssoSilent
的無訊息驗證要求中使用工作階段識別碼 (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
、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
}
}
然而,如果應用程式在單一瀏覽器工作階段中有多個使用者,或者該使用者在瀏覽器工作階段中有多個帳戶,則可能會出現無訊息登入錯誤。 如果有多個帳戶可用,可能會顯示下列錯誤:
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)
為了提升更好的效能並協助避免問題,請將 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 的互動式要求。 如果您已經擁有使用者的登入資訊,則可以傳遞 loginHint
或 sid
選擇性參數來登入特定帳戶。
使用 prompt=login 來否定 SSO
如果您想要讓 Microsoft Entra ID 提示使用者輸入其認證 (即使授權伺服器有使用中的工作階段),您可以在 MSAL.js 要求中使用登入 提示參數。 如需詳細資訊,請參閱 MSAL.js 提示行為。
在 ADAL.js 與 MSAL.js 之間共用驗證狀態
在 Microsoft Entra 驗證案例中,MSAL.js 與 ADAL.js 會出現功能同位的情況。 為了從 ADAL.js 輕鬆移轉至 MSAL.js,並且在應用程式之間共用驗證狀態,程式庫會讀取 ADAL.js 快取中代表使用者工作階段的識別碼權杖。 若要善用從 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 的詳細資訊,請參閱: