處理例外時,你可以利用例外類型本身和 ErrorCode 成員來區分例外。 有三種例外:MsalClientException、MsalServiceException 和 MsalInteractionRequiredException,它們都繼承自 MsalException。
- 當發生本地於函式庫或裝置的錯誤時,會拋出 MsalClientException。
- 當 STS 服務回傳錯誤回應或發生其他網路錯誤時,會拋出 MsalServiceException。
- 當驗證需要 UI 互動才能成功時,會擲回 MsalInteractionRequiredException。
MsalServiceException
MsalServiceException 會公開對 STS 要求所傳回的 HTTP 標頭。 你可以透過 MsalServiceException.headers() 存取它們
MsalInteractionRequiredException
MSAL4J 在呼叫 AcquireTokenSilently() 時傳回的常見狀態碼之一是 InvalidGrantError。 此狀態碼表示應用程式應再次呼叫認證函式庫,但以互動模式(使用授權代碼參數或公共客戶端應用的裝置代碼參數)。 這是因為在發出認證令牌前,還需要額外的使用者互動。
大多數情況下,當 AcquireTokenSilently 失敗時,通常是因為權杖快取中沒有符合您請求的權杖。 存取權杖在 1 小時後到期,AcquireTokenSilently 會根據刷新權杖嘗試取得新的(用 OAuth2 的術語來說,這就是「刷新權杖」流程)。 此流程也可能因多種原因而失敗,例如租戶管理員設定更嚴格的登入政策。
互動旨在讓使用者執行一個動作。 其中一些條件使用者很容易解決(例如,只需一鍵接受使用條款),而有些則無法用目前的設定解決(例如,該機器需要連接到特定的企業網路)。
MSAL 會顯示一個 reason 欄位,你可以閱讀以提供更好的使用者體驗,例如告訴使用者密碼已過期,或需要同意才能使用某些資源。 支援的值屬於 InteractionRequiredExceptionReason 列舉的一部分:
| Reason | Meaning | 建議的處理方式 |
|---|---|---|
| BasicAction | 條件可透過使用者在互動式認證流程中的互動來解決 | 使用互動式參數呼叫 acquireToken |
| 額外行動 | 此情況可透過在互動式驗證流程之外,與系統進行額外的補救性互動來解決。 | 呼叫帶有互動參數的 acquireToken,顯示解釋補救措施的訊息。 呼叫應用程式可能會選擇隱藏需要additional_action的流程,若使用者不太可能完成補救動作。 |
| 僅留訊息 | 目前無法解決這個狀況。 啟動互動式驗證流程時,會顯示一則說明條件的訊息。 | 呼叫帶有互動參數的 acquireToken,顯示解釋條件的訊息。 acquireTokenCall 在使用者讀取訊息並關閉視窗後,會回傳 UserCanceled 錯誤。 若使用者不太可能從訊息中受益,呼叫應用程式可能會選擇隱藏導致message_only的流程。 |
| 需同意 | 用戶同意資料缺失或已被撤銷。 | 呼叫所有 acquireToken,並有互動參數讓使用者同意。 |
| 使用者密碼已過期 | 使用者的密碼已過期。 | 呼叫帶有互動參數的 acquireToken,讓使用者能重設密碼 |
| 需同意 | 用戶同意缺失或已被撤銷 | 呼叫帶有互動參數的 acquireToken,讓使用者能重設密碼 |
| 沒有 | 未提供更多細節。 條件可透過使用者在互動式驗證流程中的互動來解決。 | 使用互動式參數呼叫 acquireToken |
程式碼範例
IAuthenticationResult result;
try {
PublicClientApplication application = PublicClientApplication
.builder("clientId")
.b2cAuthority("authority")
.build();
SilentParameters parameters = SilentParameters
.builder(Collections.singleton("scope"))
.build();
result = application.acquireTokenSilently(parameters).join();
}
catch (Exception ex){
if(ex instanceof MsalInteractionRequiredException){
// AcquireToken by either AuthorizationCodeParameters or DeviceCodeParameters
} else{
// Log and handle exception accordingly
}
}