Setup Apple Sign-In (Flutter + Firebase)
Wire up Sign In with Apple across iOS, Android, and web through Firebase Auth. Three systems must agree: Apple Developer Portal, Firebase Console, and app code.
Quick start (iOS-only apps)
pubspec.yaml: firebase_auth is sufficient — no extra package needed.
Future<UserCredential> signInWithApple() =>
FirebaseAuth.instance.signInWithProvider(
AppleAuthProvider()..addScope('email')..addScope('name'),
);
On iOS/macOS this presents Apple's native sheet. Enable the Apple provider in Firebase Console → Authentication → Sign-in method → Apple → Save. That's the entire setup for iOS-only.
Setup checklist (add Android/web/desktop)
Apple has no native SDK outside iOS/macOS — signInWithProvider falls back to a web redirect through https://<project>.firebaseapp.com/__/auth/handler, which needs real OAuth registration:
- Xcode: add "Sign In with Apple" capability → writes
com.apple.developer.applesignintoRunner.entitlements. Auto-registers the App ID capability in the Developer Portal on next archive with automatic signing. - Apple Developer Portal → Keys: create a key with Sign In with Apple enabled, Primary App ID = your bundle ID. Download the
.p8once; note the Key ID. - Apple Developer Portal → Identifiers → Services IDs: create one (e.g.
com.you.app.web, must differ from the bundle ID). Enable Sign In with Apple → Configure → Primary App ID, Domain =<project>.firebaseapp.com, Return URL =https://<project>.firebaseapp.com/__/auth/handler. Save all three dialogs. - Firebase Console → Apple provider → OAuth code flow configuration: Services ID, Team ID, Key ID, full
.p8contents. Save (server-side, no rebuild). - Android: register the app's SHA-1/SHA-256 in Firebase Project Settings so the redirect handler returns correctly.
Full step-by-step with exact field values: REFERENCE.md.
Code
Native sign-in, linking, unlinking, and the sign_in_with_apple package alternative (for a HIG-compliant native button): EXAMPLES.md.
Something's broken
operation-not-allowed vs invalid_client, the platform routing trap, and a one-request bisection test that pinpoints Services ID vs key misconfiguration in seconds: TROUBLESHOOTING.md.