本文概述了不同類型的錯誤,並提出處理常見登入錯誤的建議。
MSAL 錯誤處理基礎
Microsoft 驗證資源庫(MSAL)中的例外是為了讓應用程式開發者進行故障排除,而非顯示給最終使用者。 例外訊息並非本地化。
處理例外與錯誤時,您可以利用例外類型本身及錯誤代碼來區分例外。 有關錯誤代碼列表,請參閱 Microsoft Entra 認證與授權錯誤代碼。
在登入過程中,您可能會遇到關於同意、條件存取(MFA、裝置管理、基於位置的限制)、令牌發放與兌換,以及使用者屬性等錯誤。
以下章節將提供更多關於您應用程式錯誤處理的詳細資訊。
iOS / macOS MSAL 中的錯誤處理
iOS 與 macOS 的完整 MSAL 錯誤清單列在 MSALError 列舉中。
所有 MSAL 產生的錯誤都會以 MSALErrorDomain 域回傳。
系統錯誤時,MSAL 會回傳系統 API 的原始 NSError 檔案。 例如,若因網路連線不足導致令牌擷取失敗,MSAL 會回傳網域 NSURLErrorDomain 與 NSURLErrorNotConnectedToInternet 程式碼錯誤。
我們建議您在用戶端至少處理下列兩個 MSAL 錯誤:
MSALErrorInteractionRequired使用者必須進行互動式請求。 造成此錯誤的條件有很多,例如認證會話過期或需要額外的認證要求。 呼叫 MSAL 互動式憑證取得 API 以進行恢復。MSALErrorServerDeclinedScopes:部分或全部範圍遭拒絕。 決定是否只使用已授權的範圍,或停止登入流程。
Note
MSALInternalError列舉應該只用於參考和除錯。 不要試圖在執行時自動處理這些錯誤。 如果你的應用程式遇到任何屬於 MSALInternalError 的錯誤,你可能會想要顯示一則通用的使用者提示訊息,解釋發生了什麼事。
例如,代表 MSALInternalErrorBrokerResponseNotReceived 使用者沒有完成驗證,而是手動返回應用程式。 在這種情況下,你的應用程式應該會顯示一個通用錯誤訊息,說明驗證未完成,並建議他們嘗試重新驗證。
以下 Objective-C 範例程式碼展示了處理一些常見錯誤狀況的最佳實務。
MSALInteractiveTokenParameters *interactiveParameters = ...;
MSALSilentTokenParameters *silentParameters = ...;
MSALCompletionBlock completionBlock;
__block __weak MSALCompletionBlock weakCompletionBlock;
weakCompletionBlock = completionBlock = ^(MSALResult *result, NSError *error)
{
if (!error)
{
// Use result.accessToken
NSString *accessToken = result.accessToken;
return;
}
if ([error.domain isEqualToString:MSALErrorDomain])
{
switch (error.code)
{
case MSALErrorInteractionRequired:
{
// Interactive auth will be required
[application acquireTokenWithParameters:interactiveParameters
completionBlock:weakCompletionBlock];
break;
}
case MSALErrorServerDeclinedScopes:
{
// These are list of granted and declined scopes.
NSArray *grantedScopes = error.userInfo[MSALGrantedScopesKey];
NSArray *declinedScopes = error.userInfo[MSALDeclinedScopesKey];
// To continue acquiring token for granted scopes only, do the following
silentParameters.scopes = grantedScopes;
[application acquireTokenSilentWithParameters:silentParameters
completionBlock:weakCompletionBlock];
// Otherwise, instead, handle error fittingly to the application context
break;
}
case MSALErrorServerProtectionPoliciesRequired:
{
// Integrate the Intune SDK and call the
// remediateComplianceForIdentity:silent: API.
// Handle this error only if you integrated Intune SDK.
// See more info here: https://aka.ms/intuneMAMSDK
break;
}
case MSALErrorUserCanceled:
{
// The user cancelled the web auth session.
// You may want to ask the user to try again.
// Handling of this error is optional.
break;
}
case MSALErrorInternal:
{
// Log the error, then inspect the MSALInternalErrorCodeKey
// in the userInfo dictionary.
// Display generic error message to the end user
// More detailed information about the specific error
// under MSALInternalErrorCodeKey can be found in MSALInternalError enum.
NSLog(@"Failed with error %@", error);
break;
}
default:
NSLog(@"Failed with unknown MSAL error %@", error);
break;
}
return;
}
// Handle no internet connection.
if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorNotConnectedToInternet)
{
NSLog(@"No internet connection.");
return;
}
// Other errors may require trying again later,
// or reporting authentication problems to the user.
NSLog(@"Failed with error %@", error);
};
// Acquire token silently
[application acquireTokenSilentWithParameters:silentParameters
completionBlock:completionBlock];
// or acquire it interactively.
[application acquireTokenWithParameters:interactiveParameters
completionBlock:completionBlock];
let interactiveParameters: MSALInteractiveTokenParameters = ...
let silentParameters: MSALSilentTokenParameters = ...
var completionBlock: MSALCompletionBlock!
completionBlock = { (result: MSALResult?, error: Error?) in
if let result = result
{
// Use result.accessToken
let accessToken = result.accessToken
return
}
guard let error = error as NSError? else { return }
if error.domain == MSALErrorDomain, let errorCode = MSALError(rawValue: error.code)
{
switch errorCode
{
case .interactionRequired:
// Interactive auth will be required
application.acquireToken(with: interactiveParameters, completionBlock: completionBlock)
case .serverDeclinedScopes:
let grantedScopes = error.userInfo[MSALGrantedScopesKey]
let declinedScopes = error.userInfo[MSALDeclinedScopesKey]
if let scopes = grantedScopes as? [String] {
silentParameters.scopes = scopes
application.acquireTokenSilent(with: silentParameters, completionBlock: completionBlock)
}
case .serverProtectionPoliciesRequired:
// Integrate the Intune SDK and call the
// remediateComplianceForIdentity:silent: API.
// Handle this error only if you integrated Intune SDK.
// See more info here: https://aka.ms/intuneMAMSDK
break
case .userCanceled:
// The user cancelled the web auth session.
// You may want to ask the user to try again.
// Handling of this error is optional.
break
case .internal:
// Log the error, then inspect the MSALInternalErrorCodeKey
// in the userInfo dictionary.
// Display generic error message to the end user
// More detailed information about the specific error
// under MSALInternalErrorCodeKey can be found in MSALInternalError enum.
print("Failed with error \(error)");
default:
print("Failed with unknown MSAL error \(error)")
}
}
// Handle no internet connection.
if error.domain == NSURLErrorDomain && error.code == NSURLErrorNotConnectedToInternet
{
print("No internet connection.")
return
}
// Other errors may require trying again later,
// or reporting authentication problems to the user.
print("Failed with error \(error)");
}
// Acquire token silently
application.acquireToken(with: interactiveParameters, completionBlock: completionBlock)
// or acquire it interactively.
application.acquireTokenSilent(with: silentParameters, completionBlock: completionBlock)
條件存取與理賠挑戰
當以靜默方式取得權杖時,如果您嘗試存取的 API 要求 條件式存取宣告挑戰(例如 MFA 原則),您的應用程式可能會收到錯誤。
處理此錯誤的模式是透過 MSAL 互動式取得令牌。 這會提示使用者,並給予他們機會滿足所需的條件存取政策。
在某些情況下,當呼叫需要條件存取的 API 時,你可能會在錯誤中收到 API 的理據挑戰。 例如,如果條件存取政策是要有受管理的裝置(Intune),錯誤會是像 AADSTS53000:你的裝置必須被管理才能存取此資源 或類似的訊息。 在這種情況下,你可以在取得權杖的呼叫中傳遞宣告,系統便會提示使用者滿足適當的原則。
iOS 和 macOS 的 MSAL 允許你在互動式或無聲令牌取得情境下申請特定權利要求。
若要要求自訂宣告,請在 MSALSilentTokenParameters 或 MSALInteractiveTokenParameters 中指定 claimsRequest。
更多資訊請參閱 iOS 和 macOS 使用 MSAL 請求自訂理賠 。
錯誤與異常後重試
你在打電話給 MSAL 時,預期要自己執行重試政策。 MSAL 會對 Microsoft Entra 服務進行 HTTP 呼叫,偶爾會發生故障。 例如網路可能會當機或伺服器過載。
HTTP 429
當服務權杖伺服器(STS)因請求過多而超載時,會在回應欄位回傳 HTTP 錯誤 429,並提示你還要多久才能再 Retry-After 嘗試。
下一步
建議在 iOS/macOS 啟用 MSAL 的登入 功能,幫助你診斷和除錯問題。