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?