-
Notifications
You must be signed in to change notification settings - Fork 489
docs: getting started for auth firebaseUI using SwiftUI #1328
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
russellwheatley
wants to merge
2
commits into
main
Choose a base branch
from
getting-started-docs
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+369
−0
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,369 @@ | ||
| # FirebaseUI for SwiftUI | ||
|
|
||
| FirebaseUI for SwiftUI is a library built on top of Firebase Authentication that provides modern, SwiftUI-first sign-in flows for your app. | ||
|
|
||
| FirebaseUI for SwiftUI provides the following benefits: | ||
|
|
||
| - Opinionated default UI: add a complete sign-in flow with `AuthPickerView`. | ||
| - Customizable: use the built-in flow, render the default buttons in your own layout, or build a fully custom experience with `AuthService`. | ||
| - Anonymous account linking: optionally upgrade anonymous users instead of replacing them. | ||
| - Account management: built-in flows for sign-in, sign-up, password recovery, email link sign-in, reauthentication, and account management. | ||
| - Multiple providers: email/password, email link, phone authentication, Apple, Google, Facebook, Twitter, and generic OAuth/OIDC providers. | ||
| - Modern auth features: built-in support for multi-factor authentication (MFA) and async/await APIs. | ||
|
|
||
| ## Before you begin | ||
|
|
||
| FirebaseUI authentication is now delivered as Swift Package Manager packages for SwiftUI apps. | ||
|
|
||
| 1. Add Firebase to your Apple project by following the [Firebase iOS setup guide](https://firebase.google.com/docs/ios/setup). | ||
| 2. In Xcode, choose **File > Add Package Dependencies...** | ||
| 3. Add `https://github.com/firebase/FirebaseUI-iOS` | ||
| 4. Select `FirebaseAuthSwiftUI` and any provider packages you want to use: | ||
| - `FirebaseAppleSwiftUI` | ||
| - `FirebaseGoogleSwiftUI` | ||
| - `FirebaseFacebookSwiftUI` | ||
| - `FirebasePhoneAuthSwiftUI` | ||
| - `FirebaseTwitterSwiftUI` | ||
| - `FirebaseOAuthSwiftUI` | ||
| 5. Make sure your app targets iOS 17 or later. | ||
|
|
||
| Then configure Firebase when your app launches: | ||
|
|
||
| ```swift | ||
| import FirebaseAuthSwiftUI | ||
| import FirebaseCore | ||
| import SwiftUI | ||
|
|
||
| class AppDelegate: NSObject, UIApplicationDelegate { | ||
| func application( | ||
| _ application: UIApplication, | ||
| didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil | ||
| ) -> Bool { | ||
| FirebaseApp.configure() | ||
| return true | ||
| } | ||
| } | ||
|
|
||
| @main | ||
| struct YourApp: App { | ||
| @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate | ||
|
|
||
| var body: some Scene { | ||
| WindowGroup { | ||
| ContentView() | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## Set up sign-in methods | ||
|
|
||
| Before you can sign users in, enable the providers you want to support in **Authentication > Sign-in method** in the Firebase console. | ||
|
|
||
| ### Email address and password | ||
|
|
||
| Enable the **Email/Password** provider in the Firebase console. | ||
|
|
||
| Add email sign-in to your `AuthService`: | ||
|
|
||
| ```swift | ||
| let authService = AuthService() | ||
| .withEmailSignIn() | ||
| ``` | ||
|
|
||
| ### Email link authentication | ||
|
|
||
| To use passwordless email link sign-in, configure `ActionCodeSettings` and pass it into `AuthConfiguration`. | ||
|
|
||
| ```swift | ||
| let actionCodeSettings = ActionCodeSettings() | ||
| actionCodeSettings.handleCodeInApp = true | ||
| actionCodeSettings.url = URL(string: "https://yourapp.firebaseapp.com") | ||
|
|
||
| guard let bundleID = Bundle.main.bundleIdentifier else { | ||
| fatalError("Missing bundle identifier for email link authentication setup.") | ||
| } | ||
|
|
||
| actionCodeSettings.setIOSBundleID(bundleID) | ||
|
|
||
| let configuration = AuthConfiguration( | ||
| emailLinkSignInActionCodeSettings: actionCodeSettings | ||
| ) | ||
|
|
||
| let authService = AuthService(configuration: configuration) | ||
| .withEmailSignIn() | ||
| ``` | ||
|
|
||
| You must also: | ||
|
|
||
| 1. Enable **Email link (passwordless sign-in)** in the Firebase console. | ||
| 2. Add the link domain to **Authorized domains**. | ||
| 3. If you build custom views, call `authService.handleSignInLink(url:)` when the link opens your app. | ||
|
|
||
| ### Apple | ||
|
|
||
| To use Sign in with Apple: | ||
|
|
||
| 1. Enable **Apple** in the Firebase console. | ||
| 2. Add the **Sign in with Apple** capability in Xcode. | ||
| 3. Follow the Firebase guide for [Sign in with Apple on Apple platforms](https://firebase.google.com/docs/auth/ios/apple). | ||
|
|
||
| Then register the provider: | ||
|
|
||
| ```swift | ||
| let authService = AuthService() | ||
| .withAppleSignIn() | ||
| ``` | ||
|
|
||
|
|
||
| To use Google Sign-In: | ||
|
|
||
| 1. Enable **Google** in the Firebase console. | ||
| 2. Follow the Firebase guide for [Google Sign-In on Apple platforms](https://firebase.google.com/docs/auth/ios/google-signin). | ||
| 3. Add your `REVERSED_CLIENT_ID` from `GoogleService-Info.plist` to **URL Types** in your Xcode target. | ||
|
|
||
| Then register the provider: | ||
|
|
||
| ```swift | ||
| let authService = AuthService() | ||
| .withGoogleSignIn() | ||
| ``` | ||
|
|
||
|
|
||
| To use Facebook Login: | ||
|
|
||
| 1. Enable **Facebook** in the Firebase console and add your Facebook App ID and App Secret. | ||
| 2. Follow Facebook's iOS SDK setup instructions. | ||
| 3. Add `fb{your-app-id}` to **URL Types** in your Xcode target. | ||
| 4. Add `FacebookAppID` and `FacebookDisplayName` to `Info.plist`. | ||
| 5. Enable Keychain Sharing in Xcode. | ||
|
|
||
| Then register the provider: | ||
|
|
||
| ```swift | ||
| let authService = AuthService() | ||
| .withFacebookSignIn() | ||
| ``` | ||
|
|
||
| ### Phone number | ||
|
|
||
| To use phone authentication: | ||
|
|
||
| 1. Enable **Phone** in the Firebase console. | ||
| 2. Configure APNs for your app. | ||
| 3. Enable Push Notifications in Xcode. | ||
| 4. Add your Firebase **Encoded App ID** as a URL scheme for reCAPTCHA fallback. | ||
|
|
||
| Phone auth also needs the APNs token and reCAPTCHA URL handlers shown in `Handle provider callbacks` below. Add those methods to the same `AppDelegate` you use for `FirebaseApp.configure()`. | ||
|
|
||
| Then register the provider: | ||
|
|
||
| ```swift | ||
| let authService = AuthService() | ||
| .withPhoneSignIn() | ||
| ``` | ||
|
|
||
|
|
||
| To use Twitter Login: | ||
|
|
||
| 1. Enable **Twitter** in the Firebase console. | ||
| 2. Configure the provider credentials in Firebase. | ||
|
|
||
| Then register the provider: | ||
|
|
||
| ```swift | ||
| let authService = AuthService() | ||
| .withTwitterSignIn() | ||
| ``` | ||
|
|
||
| ### Generic OAuth and OIDC providers | ||
|
|
||
| FirebaseUI also supports built-in OAuth providers such as GitHub, Microsoft, and Yahoo, as well as custom OIDC providers configured in Firebase Authentication. | ||
|
|
||
| ```swift | ||
| let authService = AuthService() | ||
| .withOAuthSignIn(OAuthProviderSwift.github()) | ||
| .withOAuthSignIn(OAuthProviderSwift.microsoft()) | ||
| .withOAuthSignIn(OAuthProviderSwift.yahoo()) | ||
| ``` | ||
|
|
||
| For custom OIDC providers, configure the provider first in Firebase Authentication, then create an `OAuthProviderSwift` with your provider ID and button configuration. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: A code snippet here demonstrating the initialization of the |
||
|
|
||
| ### Handle provider callbacks | ||
|
|
||
| If you use Google Sign-In, Facebook Login, phone authentication, or email link flows, merge the following imports and methods into the same `AppDelegate` you use for `FirebaseApp.configure()`. | ||
|
|
||
| ```swift | ||
| import FacebookCore | ||
| import FirebaseAuth | ||
| import GoogleSignIn | ||
| import UIKit | ||
|
|
||
| class AppDelegate: NSObject, UIApplicationDelegate { | ||
| func application( | ||
| _ application: UIApplication, | ||
| didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data | ||
| ) { | ||
| #if DEBUG | ||
| Auth.auth().setAPNSToken(deviceToken, type: .sandbox) | ||
| #else | ||
| Auth.auth().setAPNSToken(deviceToken, type: .prod) | ||
| #endif | ||
| } | ||
|
|
||
| func application( | ||
| _ app: UIApplication, | ||
| open url: URL, | ||
| options: [UIApplication.OpenURLOptionsKey: Any] = [:] | ||
| ) -> Bool { | ||
| if Auth.auth().canHandle(url) { | ||
| return true | ||
| } | ||
|
|
||
| if ApplicationDelegate.shared.application( | ||
| app, | ||
| open: url, | ||
| sourceApplication: options[.sourceApplication] as? String, | ||
| annotation: options[.annotation] | ||
| ) { | ||
| return true | ||
| } | ||
|
|
||
| return GIDSignIn.sharedInstance.handle(url) | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## Sign in | ||
|
|
||
| To start the FirebaseUI sign-in flow, create an `AuthService`, register the providers you want, and pass it into `AuthPickerView`. | ||
|
|
||
| ### Swift | ||
|
|
||
| ```swift | ||
| import FirebaseAppleSwiftUI | ||
| import FirebaseAuthSwiftUI | ||
| import FirebaseGoogleSwiftUI | ||
| import SwiftUI | ||
|
|
||
| struct ContentView: View { | ||
| let authService: AuthService | ||
|
|
||
| init() { | ||
| let configuration = AuthConfiguration( | ||
| shouldAutoUpgradeAnonymousUsers: true, | ||
| tosUrl: URL(string: "https://example.com/terms"), | ||
| privacyPolicyUrl: URL(string: "https://example.com/privacy") | ||
| ) | ||
|
|
||
| authService = AuthService(configuration: configuration) | ||
| .withEmailSignIn() | ||
| .withAppleSignIn() | ||
| .withGoogleSignIn() | ||
| } | ||
|
|
||
| var body: some View { | ||
| AuthPickerView { | ||
| authenticatedContent | ||
| } | ||
| .environment(authService) | ||
| } | ||
|
|
||
| var authenticatedContent: some View { | ||
| NavigationStack { | ||
| VStack(spacing: 20) { | ||
| if authService.authenticationState == .authenticated { | ||
| Text("Authenticated") | ||
|
|
||
| Button("Manage Account") { | ||
| authService.isPresented = true | ||
| } | ||
| .buttonStyle(.bordered) | ||
|
|
||
| Button("Sign Out") { | ||
| Task { | ||
| try? await authService.signOut() | ||
| } | ||
| } | ||
| .buttonStyle(.borderedProminent) | ||
| } else { | ||
| Text("Not Authenticated") | ||
|
|
||
| Button("Sign In") { | ||
| authService.isPresented = true | ||
| } | ||
| .buttonStyle(.borderedProminent) | ||
| } | ||
| } | ||
| } | ||
| .onChange(of: authService.authenticationState) { _, newValue in | ||
| if newValue != .authenticating { | ||
| authService.isPresented = (newValue == .unauthenticated) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| When you use `AuthPickerView`, FirebaseUI handles the default authentication flow for you, including: | ||
|
|
||
| - Navigation between sign-in screens | ||
| - Password recovery and email link flows | ||
| - Account conflict handling | ||
| - Reauthentication for sensitive operations | ||
| - MFA resolution when enabled | ||
|
|
||
| If you want more control, you can skip `AuthPickerView` and call `AuthService` methods directly from your own views. | ||
|
|
||
| ## Sign out | ||
|
|
||
| FirebaseUI provides an async sign-out method: | ||
|
|
||
| ```swift | ||
| Task { | ||
| try await authService.signOut() | ||
| } | ||
| ``` | ||
|
|
||
| ## Customization | ||
|
|
||
| You can customize the authentication experience in a few different ways. | ||
|
|
||
| Use `AuthConfiguration` to configure behavior such as: | ||
|
|
||
| - Terms of service and privacy policy URLs | ||
| - Custom localized strings bundle | ||
| - Email link configuration | ||
| - Anonymous user upgrades | ||
| - MFA support | ||
|
|
||
| ```swift | ||
| let configuration = AuthConfiguration( | ||
| shouldAutoUpgradeAnonymousUsers: true, | ||
| customStringsBundle: .main, | ||
| tosUrl: URL(string: "https://example.com/terms"), | ||
| privacyPolicyUrl: URL(string: "https://example.com/privacy"), | ||
| mfaEnabled: true | ||
| ) | ||
| ``` | ||
|
|
||
| If you want to keep the built-in buttons but use your own layout, call `authService.renderButtons()`. | ||
|
|
||
| If you want a fully custom experience, build your own views and call methods such as: | ||
|
|
||
| - `authService.signIn(_:)` | ||
| - `authService.signIn(email:password:)` | ||
| - `authService.createUser(email:password:)` | ||
| - `authService.verifyPhoneNumber(phoneNumber:)` | ||
| - `authService.signInWithPhoneNumber(verificationID:verificationCode:)` | ||
|
|
||
| You can also register your own provider button by conforming to `AuthProviderUI` and calling `authService.registerProvider(providerWithButton:)`. | ||
|
|
||
| ## Next steps | ||
|
|
||
| - See `FirebaseSwiftUI/README.md` for the full API reference and advanced usage. | ||
| - See `samples/swiftui/FirebaseSwiftUISample` for a working example app. | ||
| - For provider-specific setup details, refer to the Firebase Authentication docs for the provider you are enabling. | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Link to Firebase console here: