MSAL Java 中的例外

處理例外時,你可以利用例外類型本身和 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
    }
}