この記事では、さまざまな種類のエラーの概要と、一般的なサインイン エラーを処理するための推奨事項について説明します。
MSAL エラー処理の基本
Microsoft Authentication Library (MSAL) の例外は、エンド ユーザーに表示されるのではなく、アプリ開発者がトラブルシューティングを行うために使用されます。 例外メッセージはローカライズされません。
例外とエラーを処理する場合は、例外の種類自体とエラー コードを使用して例外を区別できます。 エラー コードの一覧については、認証と承認のエラー コードMicrosoft Entra参照してください。
サインイン エクスペリエンス中に、同意、条件付きアクセス (MFA、デバイス管理、場所ベースの制限)、トークンの発行と利用、およびユーザー プロパティに関するエラーが発生する場合があります。
次のセクションでは、アプリのエラー処理の詳細について説明します。
iOS/macOS 用 MSAL でのエラー処理
iOS および macOS の MSAL エラーの完全な一覧は、 MSALError 列挙型に記載されています。
MSAL で生成されたすべてのエラーは、 MSALErrorDomain ドメインで返されます。
システム エラーの場合、MSAL はシステム API から元の NSError を返します。 たとえば、ネットワーク接続がないためにトークンの取得が失敗した場合、MSAL は NSURLErrorDomain ドメインと NSURLErrorNotConnectedToInternet コードでエラーを返します。
クライアント側では、少なくとも次の 2 つの 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 を使用すると、対話型トークン取得シナリオとサイレント トークン取得シナリオの両方で特定の要求を要求できます。
カスタム要求を要求するには、claimsRequestまたはMSALSilentTokenParametersでMSALInteractiveTokenParametersを指定します。
詳細については、「 iOS および macOS 用の MSAL を使用してカスタム要求を要求 する」を参照してください。
エラーと例外の後の再試行
MSAL を呼び出すときに、独自の再試行ポリシーを実装する必要があります。 MSAL では、Microsoft Entra サービスへの HTTP 呼び出しが行われ、エラーが発生することがあります。 たとえば、ネットワークがダウンしたり、サーバーが過負荷になったりする可能性があります。
HTTP 429
サービス トークン サーバー (STS) が多すぎる要求でオーバーロードされると、HTTP エラー 429 が返され、 Retry-After 応答フィールドで再試行できるまでの時間に関するヒントが返されます。
次のステップ
問題の診断とデバッグに役立つ 、iOS/macOS 用の MSAL でのログ記録 を有効にすることを検討してください。