-
Notifications
You must be signed in to change notification settings - Fork 78
docs: Add Firebase IDP docs #395
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,258 @@ | ||||||||||||||||||||||||||||||||||||||
| # Setup | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Firebase authentication works differently from other identity providers in Serverpod. Instead of handling authentication directly, Serverpod's Firebase integration acts as a bridge between Firebase Authentication and your Serverpod backend. Firebase handles the actual sign-in process through its own SDKs and UI components, while Serverpod syncs the authenticated user and manages the server-side session. | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| This approach allows you to use any authentication method supported by Firebase (email/password, phone, Google, Apple, Facebook, etc.) while maintaining a unified user system in your Serverpod backend. | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :::caution | ||||||||||||||||||||||||||||||||||||||
| You need to install the auth module before you continue, see [Setup](../../setup). | ||||||||||||||||||||||||||||||||||||||
| ::: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ## Prerequisites | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Before setting up Firebase authentication, ensure you have: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - A Firebase project (create one at [Firebase Console](https://console.firebase.google.com/)) | ||||||||||||||||||||||||||||||||||||||
| - Firebase CLI installed (`npm install -g firebase-tools`) | ||||||||||||||||||||||||||||||||||||||
| - FlutterFire CLI installed (`dart pub global activate flutterfire_cli`) | ||||||||||||||||||||||||||||||||||||||
| - At least one authentication method enabled in your Firebase project | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+11
to
+18
Collaborator
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. Suggestion: Instead of a "Prerequisites" session, can we introduce each one along the way as steps on the guide? For example, the last one (having methods enabled) is already shown below, so it is not actually a prerequisite for the guide. |
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ## Create your credentials | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ### Generate Service Account Key | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| The server needs service account credentials to verify Firebase ID tokens. To create a new key: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| 1. Go to the [Firebase Console](https://console.firebase.google.com/) | ||||||||||||||||||||||||||||||||||||||
| 2. Select your project | ||||||||||||||||||||||||||||||||||||||
| 3. Navigate to **Project settings** > **Service accounts** | ||||||||||||||||||||||||||||||||||||||
| 4. Click **Generate new private key**, then **Generate key** | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| This downloads a JSON file containing your service account credentials. | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ### Enable Authentication Methods | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| In the Firebase Console, enable the authentication methods you want to support: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| 1. Go to **Authentication** > **Sign-in method** | ||||||||||||||||||||||||||||||||||||||
| 2. Enable your desired providers (Email/Password, Phone, Google, Apple, etc.) | ||||||||||||||||||||||||||||||||||||||
| 3. Configure each provider according to Firebase's documentation | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|  | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ## Server-side configuration | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ### Store the Service Account Key | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| This can be done by pasting the contents of the JSON file into the `firebaseServiceAccountKey` key in the `config/passwords.yaml` file or setting as value of the `SERVERPOD_PASSWORD_firebaseServiceAccountKey` environment variable. Alternatively, you can read the file contents directly using the `FirebaseServiceAccountCredentials.fromJsonFile()` method. | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ```yaml | ||||||||||||||||||||||||||||||||||||||
| development: | ||||||||||||||||||||||||||||||||||||||
| firebaseServiceAccountKey: | | ||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||
| "type": "service_account", | ||||||||||||||||||||||||||||||||||||||
| "project_id": "your-project-id", | ||||||||||||||||||||||||||||||||||||||
| "private_key_id": "...", | ||||||||||||||||||||||||||||||||||||||
| "private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n", | ||||||||||||||||||||||||||||||||||||||
| "client_email": "firebase-adminsdk-xxxxx@your-project-id.iam.gserviceaccount.com", | ||||||||||||||||||||||||||||||||||||||
| "client_id": "...", | ||||||||||||||||||||||||||||||||||||||
| "auth_uri": "https://accounts.google.com/o/oauth2/auth", | ||||||||||||||||||||||||||||||||||||||
| "token_uri": "https://oauth2.googleapis.com/token" | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+51
to
+64
Collaborator
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. Suggestion: Can we add a similar example to the Google Sign-In setup guide? This is very good for users to visualize. |
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :::warning | ||||||||||||||||||||||||||||||||||||||
| The service account key gives admin access to your Firebase project and should not be version controlled. Store it securely using environment variables or secret management. | ||||||||||||||||||||||||||||||||||||||
| ::: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ### Configure the Firebase Identity Provider | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| In your main `server.dart` file, configure the Firebase identity provider: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ```dart | ||||||||||||||||||||||||||||||||||||||
| import 'package:serverpod/serverpod.dart'; | ||||||||||||||||||||||||||||||||||||||
| import 'package:serverpod_auth_idp_server/core.dart'; | ||||||||||||||||||||||||||||||||||||||
| import 'package:serverpod_auth_idp_server/providers/firebase.dart'; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| void run(List<String> args) async { | ||||||||||||||||||||||||||||||||||||||
| final pod = Serverpod( | ||||||||||||||||||||||||||||||||||||||
| args, | ||||||||||||||||||||||||||||||||||||||
| Protocol(), | ||||||||||||||||||||||||||||||||||||||
| Endpoints(), | ||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| pod.initializeAuthServices( | ||||||||||||||||||||||||||||||||||||||
| tokenManagerBuilders: [ | ||||||||||||||||||||||||||||||||||||||
| JwtConfigFromPasswords(), | ||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||
| identityProviderBuilders: [ | ||||||||||||||||||||||||||||||||||||||
| FirebaseIdpConfig( | ||||||||||||||||||||||||||||||||||||||
| credentials: FirebaseServiceAccountCredentials.fromJsonString( | ||||||||||||||||||||||||||||||||||||||
| pod.getPassword('firebaseServiceAccountKey')!, | ||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| await pod.start(); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :::tip | ||||||||||||||||||||||||||||||||||||||
| You can use `FirebaseIdpConfigFromPasswords()` to automatically load credentials from `config/passwords.yaml` or the `SERVERPOD_PASSWORD_firebaseServiceAccountKey` environment variable: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ```dart | ||||||||||||||||||||||||||||||||||||||
| identityProviderBuilders: [ | ||||||||||||||||||||||||||||||||||||||
| FirebaseIdpConfigFromPasswords(), | ||||||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ::: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ### Expose the Endpoint | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Create an endpoint that extends `FirebaseIdpBaseEndpoint` to expose the Firebase authentication API: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ```dart | ||||||||||||||||||||||||||||||||||||||
| import 'package:serverpod_auth_idp_server/providers/firebase.dart'; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| class FirebaseIdpEndpoint extends FirebaseIdpBaseEndpoint {} | ||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ### Generate and Migrate | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Run the following commands to generate client code and create the database migration: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||
| serverpod generate | ||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Then create and apply the migration: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||
| serverpod create-migration | ||||||||||||||||||||||||||||||||||||||
| docker compose up --build --detach | ||||||||||||||||||||||||||||||||||||||
| dart run bin/main.dart --role maintenance --apply-migrations | ||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| More detailed instructions can be found in the general [identity providers setup section](../../setup#identity-providers-configuration). | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+124
to
+140
Collaborator
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. Suggestion: Suppress this details and keep only the reference to the providers configuration, as we do on the other provider setup guides. This is intentional to avoid making specific guides more verbose with steps that users might already be familiar while also simplifying future evolution of the docs (like when introducing new migrations UX). For consistency, I would suggest having the same wording we use on others:
Suggested change
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ### Basic configuration options | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| - `credentials`: Required. Firebase service account credentials for verifying ID tokens. See the [configuration section](./configuration) for different ways to load credentials. | ||||||||||||||||||||||||||||||||||||||
| - `firebaseAccountDetailsValidation`: Optional. Validation function for Firebase account details. By default, this validates that the email is verified when present (phone-only authentication is allowed). See the [configuration section](./configuration#custom-account-validation) for customization options. | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ## Client-side configuration | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+147
to
+148
Collaborator
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. Suggestion: Add a brief summary of the session here, like saying that we will use the official Firebase packages and that the below steps follow standard Firebase usage guide. If there is one, it is also worth referencing an official Firebase troubleshooting guide. Although this is slightly redundant with the general description of the setup, it is here that the information is useful, so it is worth repeating. |
||||||||||||||||||||||||||||||||||||||
| ### Install Required Packages | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Add the Firebase and Serverpod authentication packages to your Flutter project: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||
| flutter pub add firebase_core firebase_auth serverpod_auth_idp_flutter_firebase | ||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| If you want to use Firebase's pre-built UI components, also add: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||
| flutter pub add firebase_ui_auth | ||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ### Configure FlutterFire | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Run the FlutterFire CLI to configure Firebase for your Flutter project: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ```bash | ||||||||||||||||||||||||||||||||||||||
| flutterfire configure | ||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| This generates a `firebase_options.dart` file with your platform-specific Firebase configuration. | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ### Initialize Firebase and Serverpod | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| In your `main.dart`, initialize both Firebase and the Serverpod client: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ```dart | ||||||||||||||||||||||||||||||||||||||
| import 'package:firebase_core/firebase_core.dart'; | ||||||||||||||||||||||||||||||||||||||
| import 'package:flutter/material.dart'; | ||||||||||||||||||||||||||||||||||||||
| import 'package:serverpod_flutter/serverpod_flutter.dart'; | ||||||||||||||||||||||||||||||||||||||
| import 'package:serverpod_auth_idp_flutter_firebase/serverpod_auth_idp_flutter_firebase.dart'; | ||||||||||||||||||||||||||||||||||||||
| import 'package:your_client/your_client.dart'; | ||||||||||||||||||||||||||||||||||||||
| import 'firebase_options.dart'; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| late Client client; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| void main() async { | ||||||||||||||||||||||||||||||||||||||
| WidgetsFlutterBinding.ensureInitialized(); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Initialize Firebase | ||||||||||||||||||||||||||||||||||||||
| await Firebase.initializeApp( | ||||||||||||||||||||||||||||||||||||||
| options: DefaultFirebaseOptions.currentPlatform, | ||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Create the Serverpod client | ||||||||||||||||||||||||||||||||||||||
| client = Client('http://localhost:8080/') | ||||||||||||||||||||||||||||||||||||||
| ..connectivityMonitor = FlutterConnectivityMonitor() | ||||||||||||||||||||||||||||||||||||||
| ..authSessionManager = FlutterAuthSessionManager(); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Initialize Serverpod auth | ||||||||||||||||||||||||||||||||||||||
| await client.auth.initialize(); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Initialize Firebase sign-in service (enables automatic sign-out sync) | ||||||||||||||||||||||||||||||||||||||
| client.auth.initializeFirebaseSignIn(); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| runApp(const MyApp()); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ## The authentication flow | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Understanding the Firebase authentication flow helps when building custom integrations: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| 1. **User initiates sign-in** with Firebase using `firebase_auth` or `firebase_ui_auth` | ||||||||||||||||||||||||||||||||||||||
| 2. **Firebase authenticates** the user and returns a `firebase_auth.User` object | ||||||||||||||||||||||||||||||||||||||
| 3. **Your app calls** `FirebaseAuthController.login(user)` with the Firebase user | ||||||||||||||||||||||||||||||||||||||
| 4. **The controller extracts** the Firebase ID token from the user | ||||||||||||||||||||||||||||||||||||||
| 5. **Token is sent** to your server's `firebaseIdp.login()` endpoint | ||||||||||||||||||||||||||||||||||||||
| 6. **Server validates** the JWT using the service account credentials | ||||||||||||||||||||||||||||||||||||||
| 7. **Server creates or updates** the user account and issues a Serverpod session token | ||||||||||||||||||||||||||||||||||||||
| 8. **Client session is updated** and the user is authenticated with Serverpod | ||||||||||||||||||||||||||||||||||||||
|
Collaborator
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.
Suggested change
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :::info | ||||||||||||||||||||||||||||||||||||||
| The `initializeFirebaseSignIn()` call in the client setup automatically signs out from Firebase when the user signs out from Serverpod, keeping both systems in sync. | ||||||||||||||||||||||||||||||||||||||
|
Collaborator
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. Suggestion: The way I read this is that the call in itself will sign out (once), but not that it will keep monitoring changes. Just a small wording suggestion to make it clearer:
Suggested change
|
||||||||||||||||||||||||||||||||||||||
| ::: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ## Present the authentication UI | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ### Using FirebaseAuthController | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| The `FirebaseAuthController` handles syncing Firebase authentication state with your Serverpod backend. After a user signs in with Firebase, pass the Firebase user to the controller: | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| ```dart | ||||||||||||||||||||||||||||||||||||||
| import 'package:firebase_auth/firebase_auth.dart' as firebase_auth; | ||||||||||||||||||||||||||||||||||||||
| import 'package:serverpod_auth_idp_flutter_firebase/serverpod_auth_idp_flutter_firebase.dart'; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Create the controller | ||||||||||||||||||||||||||||||||||||||
| final controller = FirebaseAuthController( | ||||||||||||||||||||||||||||||||||||||
| client: client, | ||||||||||||||||||||||||||||||||||||||
| onAuthenticated: () { | ||||||||||||||||||||||||||||||||||||||
| // User successfully synced with Serverpod | ||||||||||||||||||||||||||||||||||||||
| // NOTE: Do not navigate here - use client.auth.authInfoListenable instead | ||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||
| onError: (error) { | ||||||||||||||||||||||||||||||||||||||
| ScaffoldMessenger.of(context).showSnackBar( | ||||||||||||||||||||||||||||||||||||||
| SnackBar(content: Text('Error: $error')), | ||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // After user signs in with Firebase | ||||||||||||||||||||||||||||||||||||||
| final firebaseUser = firebase_auth.FirebaseAuth.instance.currentUser; | ||||||||||||||||||||||||||||||||||||||
| if (firebaseUser != null) { | ||||||||||||||||||||||||||||||||||||||
| await controller.login(firebaseUser); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| For details on building custom authentication UIs and integrating with `firebase_ui_auth`, see the [customizing the UI section](./customizing-the-ui). | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+227
to
+258
Collaborator
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. Suggestion: This session is about |
||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| # Configuration | ||
|
|
||
| This page covers configuration options for the Firebase identity provider beyond the basic setup. | ||
|
|
||
| ## Configuration options | ||
|
|
||
| Below is a non-exhaustive list of some of the most common configuration options. For more details on all options, check the `FirebaseIdpConfig` in-code documentation. | ||
|
|
||
| ### Loading Firebase Credentials | ||
|
|
||
| You can load Firebase service account credentials in several ways: | ||
|
|
||
| **From JSON string (recommended for production):** | ||
|
|
||
| ```dart | ||
| final firebaseIdpConfig = FirebaseIdpConfig( | ||
| credentials: FirebaseServiceAccountCredentials.fromJsonString( | ||
| pod.getPassword('firebaseServiceAccountKey')!, | ||
| ), | ||
| ); | ||
| ``` | ||
|
|
||
| **From JSON file:** | ||
|
|
||
| ```dart | ||
| import 'dart:io'; | ||
|
|
||
| final firebaseIdpConfig = FirebaseIdpConfig( | ||
| credentials: FirebaseServiceAccountCredentials.fromJsonFile( | ||
| File('config/firebase_service_account_key.json'), | ||
| ), | ||
| ); | ||
| ``` | ||
|
|
||
| **From JSON map:** | ||
|
|
||
| ```dart | ||
| final firebaseIdpConfig = FirebaseIdpConfig( | ||
| credentials: FirebaseServiceAccountCredentials.fromJson({ | ||
| 'type': 'service_account', | ||
| 'project_id': 'your-project-id', | ||
| 'private_key_id': '...', | ||
| 'private_key': '-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n', | ||
| 'client_email': 'firebase-adminsdk-xxxxx@your-project-id.iam.gserviceaccount.com', | ||
| 'client_id': '...', | ||
| 'auth_uri': 'https://accounts.google.com/o/oauth2/auth', | ||
| 'token_uri': 'https://oauth2.googleapis.com/token', | ||
| }), | ||
| ); | ||
| ``` | ||
|
|
||
| ### Custom Account Validation | ||
|
|
||
| You can customize the validation for Firebase account details before allowing sign-in. By default, the validation requires the email to be verified when present (phone-only authentication is allowed). | ||
|
|
||
| The default validation logic: | ||
|
|
||
| ```dart | ||
| static void validateFirebaseAccountDetails( | ||
| final FirebaseAccountDetails accountDetails, | ||
| ) { | ||
| // Firebase accounts may not have email if using phone auth | ||
| // Only validate verifiedEmail if email is present | ||
| if (accountDetails.email != null && accountDetails.verifiedEmail != true) { | ||
| throw FirebaseUserInfoMissingDataException(); | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| To customize validation, provide your own `firebaseAccountDetailsValidation` function: | ||
|
|
||
| ```dart | ||
| final firebaseIdpConfig = FirebaseIdpConfig( | ||
| credentials: FirebaseServiceAccountCredentials.fromJsonString( | ||
| pod.getPassword('firebaseServiceAccountKey')!, | ||
| ), | ||
| firebaseAccountDetailsValidation: (accountDetails) { | ||
| // Require verified email (even for phone auth) | ||
| if (accountDetails.verifiedEmail != true) { | ||
| throw Exception('Email must be verified'); | ||
| } | ||
|
|
||
| // Restrict to specific email domain | ||
| if (accountDetails.email != null && | ||
| !accountDetails.email!.endsWith('@example.com')) { | ||
| throw Exception('Only @example.com emails allowed'); | ||
| } | ||
| }, | ||
| ); | ||
| ``` | ||
|
|
||
| ### FirebaseAccountDetails | ||
|
|
||
| The `firebaseAccountDetailsValidation` callback receives a `FirebaseAccountDetails` record with the following properties: | ||
|
|
||
| | Property | Type | Description | | ||
| |----------|------|-------------| | ||
| | `userIdentifier` | `String` | The Firebase user's unique identifier (UID) | | ||
| | `email` | `String?` | The user's email address (null for phone-only auth) | | ||
| | `fullName` | `String?` | The user's display name from Firebase | | ||
| | `image` | `Uri?` | URL to the user's profile image | | ||
| | `verifiedEmail` | `bool?` | Whether the email is verified | | ||
| | `phone` | `String?` | The user's phone number (for phone auth) | | ||
|
|
||
| Example of accessing these properties: | ||
|
|
||
| ```dart | ||
| firebaseAccountDetailsValidation: (accountDetails) { | ||
| print('Firebase UID: ${accountDetails.userIdentifier}'); | ||
| print('Email: ${accountDetails.email}'); | ||
| print('Email verified: ${accountDetails.verifiedEmail}'); | ||
| print('Display name: ${accountDetails.fullName}'); | ||
| print('Profile image: ${accountDetails.image}'); | ||
| print('Phone: ${accountDetails.phone}'); | ||
|
|
||
| // Custom validation logic | ||
| if (accountDetails.email == null && accountDetails.phone == null) { | ||
| throw Exception('Either email or phone is required'); | ||
| } | ||
| }, | ||
| ``` | ||
|
|
||
| :::info | ||
| The properties available depend on the Firebase authentication method used. For example, `phone` is only populated for phone authentication, and `email` may be null if the user signed in with phone only. | ||
| ::: |
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.
Suggestion: Add ending dot to all entries on lists. This is a general suggestion for all lists (numbered or not) to make it more syntactically correct and consistent with other lists throughout the authentication docs. We usually have lists that are either an introductory stem (like this one) or a sequence of sentences, which both require punctuation.