| name | firebaseui-ios-getting-started |
| description | Sets up FirebaseUI for SwiftUI authentication in a consumer iOS app. Use when adding FirebaseUI-iOS auth, FirebaseAuthSwiftUI, AuthPickerView, or default FirebaseUI SwiftUI sign-in views to an app repo. |
FirebaseUI iOS Getting Started
Use this skill when the user wants FirebaseUI for SwiftUI authentication added to their own iOS app repo. Assume the app should use FirebaseUI's default AuthPickerView unless the user asks for custom auth UI.
Default Workflow
-
Inspect the app structure before editing:
- Find the app target, bundle identifier, minimum iOS version, Swift version, package manager, and SwiftUI app entry point.
- Find existing Firebase setup:
GoogleService-Info.plist, FirebaseApp.configure(), Firebase package dependencies, URL types, entitlements, and any auth UI.
- Identify the requested sign-in providers. If the user did not specify providers, default to email/password only.
-
Verify project requirements:
- iOS deployment target must be iOS 17 or newer.
- Swift language version must be Swift 6.0 or compatible with the FirebaseUI SwiftUI products.
- The app must use a
GoogleService-Info.plist downloaded from the user's Firebase project for the exact iOS bundle ID. Do not invent Firebase config values or reuse sample config.
-
Add dependencies from Swift Package Manager:
- Package URL:
https://github.com/firebase/FirebaseUI-iOS
- Required product:
FirebaseAuthSwiftUI
- Add provider products only when the app uses them:
FirebaseAppleSwiftUI for Sign in with Apple
FirebaseGoogleSwiftUI for Google
FirebaseFacebookSwiftUI for Facebook
FirebasePhoneAuthSwiftUI for Phone
FirebaseTwitterSwiftUI for Twitter
FirebaseOAuthSwiftUI for GitHub, Microsoft, Yahoo, or custom OAuth/OIDC
-
Configure Firebase at app launch:
- Import
FirebaseCore.
- Call
FirebaseApp.configure() once during launch.
- For SwiftUI apps, use an
UIApplicationDelegateAdaptor if there is no existing app delegate.
-
Create one parent-owned AuthService:
- Initialize it once in a parent view, not inside frequently recreated child views.
- For SwiftUI views, keep the primary owner in
@State so the @Observable service persists across view updates.
- Chain provider registration methods that match the dependencies.
- Inject it with
.environment(authService) above AuthPickerView and any authenticated content that needs auth state.
-
Add the default auth surface:
- Wrap authenticated app content in
AuthPickerView.
- Open the auth sheet by setting
authService.isPresented = true.
- Use
authService.authenticationState and authService.currentUser for simple signed-in/signed-out UI.
-
Validate:
- Run the repo's normal package resolution/build command, preferably for the real app scheme.
- If there is no obvious command, inspect available schemes and run an iOS simulator build with
xcodebuild.
- Fix compile errors caused by missing imports, package products, deployment target, or app delegate URL handling.
Minimal Default Views Pattern
Adapt names to the user's app. Preserve any existing app delegate and Firebase setup instead of duplicating it.
import FirebaseAuthSwiftUI
import FirebaseCore
import SwiftUI
class AppDelegate: NSObject, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
FirebaseApp.configure()
return true
}
}
@main
struct YourApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
import FirebaseAuth
import FirebaseAuthSwiftUI
import SwiftUI
struct ContentView: View {
@State private var authService: AuthService
init() {
_authService = State(initialValue: AuthService(configuration: AuthConfiguration())
.withEmailSignIn())
}
var body: some View {
AuthPickerView {
NavigationStack {
VStack {
Text("Authenticated")
Button("Manage Account") {
authService.isPresented = true
}
Button("Sign Out") {
Task {
try? await authService.signOut()
}
}
}
}
}
.environment(authService)
}
}
Provider Setup
Only add provider setup for providers the app actually uses.
- Email/password: add
FirebaseAuthSwiftUI, call .withEmailSignIn(), and ensure Email/Password is enabled in Firebase Console Authentication.
- Google: add
FirebaseGoogleSwiftUI, call .withGoogleSignIn(), add the REVERSED_CLIENT_ID from GoogleService-Info.plist as a URL scheme, and route incoming URLs through GIDSignIn.sharedInstance.handle(url) if the app delegate handles URLs manually.
- Apple: add
FirebaseAppleSwiftUI, call .withAppleSignIn(), enable Sign in with Apple in the app's capabilities/entitlements and in Firebase Console.
- Facebook: add
FirebaseFacebookSwiftUI, call .withFacebookSignIn(), add fb{app-id} as a URL scheme, set FacebookAppID, FacebookClientToken, and FacebookDisplayName in Info.plist, and forward launch/open-url events to ApplicationDelegate.shared.
- Phone: add
FirebasePhoneAuthSwiftUI, call .withPhoneSignIn(), enable Phone in Firebase Console. If the app has an app delegate, preserve Auth.auth().setAPNSToken(...), Auth.auth().canHandleNotification(...), and Auth.auth().canHandle(url) handling when present.
- OAuth/OIDC: add
FirebaseOAuthSwiftUI, call .withOAuthSignIn(...), and ensure the provider is configured in Firebase Console before coding the app UI.
- Email link: configure
ActionCodeSettings with handleCodeInApp = true, a valid URL/domain for the Firebase project, and setIOSBundleID(Bundle.main.bundleIdentifier!).
Gotchas
- Do not proceed silently if
GoogleService-Info.plist is missing. Ask the user to download it from Firebase Console or confirm where it lives.
- Do not hardcode sample project Firebase values, reversed client IDs, Facebook app IDs, OAuth domains, or bundle IDs.
- Do not add every FirebaseUI provider by default. Each extra provider usually requires Firebase Console and
Info.plist or entitlement setup.
- Do not create multiple
AuthService instances for the same auth flow. It owns presentation and authentication state; in SwiftUI, prefer a parent-owned @State instance unless the app already has a stronger owner for auth state.
- If app code reads
authService.currentUser?.email, uid, or other User members, import FirebaseAuth in addition to FirebaseAuthSwiftUI.
AuthPickerView already handles default navigation, account conflict resolution, MFA flows, errors, and reauthentication for built-in default views. Avoid reimplementing those unless the user asks for custom views.
- For custom views, sensitive operations such as account deletion, password updates, and MFA unenrollment can throw reauthentication errors that default views would otherwise handle.
- FirebaseUI
14.x does not include the FirebaseAuthSwiftUI product, so it is not a valid fallback for this SwiftUI workflow.
- If tagged FirebaseUI releases fail under Swift 6/Xcode with package-internal concurrency errors, check the upstream FirebaseUI SwiftUI docs/sample and consider the current
main branch only after documenting the reproducibility tradeoff.
- If Xcode package resolution gets stuck on a stale DerivedData checkout, validate with a project-local package cache, for example
xcodebuild ... -clonedSourcePackagesDirPath SourcePackages, then remove the generated SourcePackages directory before finishing.
- Xcode previews may fail if a preview instantiates a view that creates
AuthService before FirebaseApp.configure() runs. Fix previews by calling if FirebaseApp.app() == nil { FirebaseApp.configure() } in the preview setup.
Source References
Use these when details are needed beyond this skill:
- FirebaseUI SwiftUI docs:
https://github.com/firebase/FirebaseUI-iOS/blob/main/FirebaseSwiftUI/README.md
- FirebaseUI SwiftUI sample:
https://github.com/firebase/FirebaseUI-iOS/tree/main/samples/swiftui/FirebaseSwiftUISample
- Firebase iOS setup:
https://firebase.google.com/docs/ios/setup
- Firebase Auth provider setup:
https://firebase.google.com/docs/auth
Validation Checklist
Before finishing, confirm:
- The FirebaseUI package products match the imported modules and
.with...SignIn() calls.
GoogleService-Info.plist is included in the app target resources, not just present on disk.
FirebaseApp.configure() is called once before auth UI is used.
- URL schemes and app delegate URL handling match the enabled OAuth providers.
- The app builds for an iOS simulator or the repo's normal CI build command.
- The final response names any Firebase Console steps the user must complete manually.