ASAuthorizationControllerDelegate always returns .canceled for Face ID passcode fallback and failed attempts

6 days ago 9
ARTICLE AD BOX

I’m implementing Sign in with Apple / Passkeys using ASAuthorizationControllerDelegate and handling errors via:

func authorizationController( controller: ASAuthorizationController, didCompleteWithError error: Error ) { guard let authError = error as? ASAuthorizationError else { print("Unknown error:", error) return } switch authError.code { case .canceled: print("User canceled authentication") case .failed: print("Authorization failed (generic)") case .invalidResponse: print("Invalid response from Apple") case .notHandled: print("Authorization not handled") case .unknown: print("Unknown authorization error") @unknown default: print("Future unknown error") } }

However, I’m consistently seeing .canceled in all of the following situations: • User taps the ❌ button → .canceled (expected) • User cancels during Face ID → .canceled • Face ID fails and falls back to device passcode • User enters the wrong passcode → still .canceled

I never receive .failed for passcode failures or biometric fallback failures — only .canceled.

Questions

Is this the expected behavior for ASAuthorizationController? Why does a failed passcode attempt result in .canceled instead of .failed? Is there any supported way to differentiate user cancellation vs authentication failure (Face ID / passcode) using this API? When should .failed actually be expected to occur?

ASAuthorizationError.Code

Read Entire Article