Ajouter un flux d'authentification utilisateur à une application Flutter à l'aide de FirebaseUI

1. Avant de commencer

Dans cet atelier de programmation, vous allez apprendre à ajouter Firebase Authentication à votre application Flutter à l'aide du package UI FlutterFire. Avec ce package, vous allez ajouter l'authentification par e-mail/mot de passe et l'authentification Google Sign-In à une application Flutter. Vous allez également découvrir comment configurer un projet Firebase et utiliser la CLI FlutterFire pour initialiser Firebase dans votre application Flutter.

Prérequis

Cet atelier de programmation suppose que vous avez une certaine expérience de Flutter. Dans le cas contraire, vous devriez d'abord vous familiariser avec ses principes de base. Les liens suivants proposent des informations utiles :

Vous devez également avoir une certaine expérience de Firebase, mais ce n'est pas grave si vous n'avez jamais ajouté Firebase à un projet Flutter. Si vous ne connaissez pas la console Firebase, ou si vous ne connaissez pas la solution, consultez d'abord les liens suivants:

Ce que vous allez créer

Cet atelier de programmation vous explique comment créer le flux d'authentification d'une application Flutter à l'aide de Firebase pour l'authentification. L'application comprendra un écran de connexion, un écran « S'inscrire », un écran de récupération de mot de passe et un écran de profil utilisateur.

6604fc9157f2c6ae.png eab9509a41074930.png Da49189a5838e0bb.png B2ccfb3632b77878.png

Points abordés

Cet atelier de programmation aborde les points suivants:

  • Ajouter Firebase à une application Flutter
  • Configuration de la console Firebase
  • Ajouter Firebase à votre application à l'aide de la CLI Firebase
  • Utiliser la CLI FlutterFire pour générer une configuration Firebase en Dart
  • Ajouter Firebase Authentication à votre application Flutter
  • Configuration de Firebase Authentication dans la console
  • Ajouter une adresse e-mail et un mot de passe de connexion avec le package firebase_ui_auth
  • Ajouter l'enregistrement des utilisateurs avec le package firebase_ui_auth
  • Vous avez ajouté une page "Mot de passe oublié"
  • Ajouter Google Sign-In avec firebase_ui_auth
  • Configurer votre application pour qu'elle fonctionne avec plusieurs fournisseurs de connexion
  • Ajouter un écran de profil utilisateur à votre application avec le package firebase_ui_auth

Cet atelier de programmation concerne spécifiquement l'ajout d'un système d'authentification robuste à l'aide du package firebase_ui_auth. Comme vous le verrez, l'ensemble de cette application, avec toutes les fonctionnalités ci-dessus, peut être implémenté avec environ 100 lignes de code.

Prérequis

  • Connaissances pratiques de Flutter et du SDK installé
  • Un éditeur de texte (les IDE JetBrains, Android Studio et VS Code sont compatibles avec Flutter)
  • Le navigateur Google Chrome ou votre autre cible de développement préférée pour Flutter (Certaines commandes de terminal dans cet atelier de programmation supposent que vous exécutez votre application sur Chrome.)

2. Créer et configurer un projet Firebase

La première tâche que vous devez accomplir consiste à créer un projet Firebase dans la console Web de Firebase.

Créer un projet Firebase

  1. Connectez-vous à Firebase.
  2. Dans la console Firebase, cliquez sur Ajouter un projet (ou Créer un projet), puis saisissez un nom pour votre projet Firebase (par exemple, FlutterFire-UI-Codelab).

df42a5e3d9584b48.png

  1. Cliquez sur les options de création de projet. Si vous y êtes invité, acceptez les conditions d'utilisation de Firebase. Ignorez la configuration de Google Analytics, car vous n'utiliserez pas Analytics pour cette application.

D1fcec48bf251eaa.png

Pour en savoir plus sur les projets Firebase, consultez Comprendre les projets Firebase.

Activer la connexion par e-mail pour Firebase Authentication

L'application que vous développez utilise Firebase Authentication pour permettre à vos utilisateurs de se connecter à votre application. Elle permet également aux nouveaux utilisateurs de s'inscrire depuis l'application Flutter.

Firebase Authentication doit être activé via la console Firebase et nécessite une configuration particulière une fois activé.

Pour autoriser les utilisateurs à se connecter à l'application Web, vous devez d'abord utiliser la méthode de connexion Adresse e-mail/Mot de passe. Vous ajouterez ensuite la méthode Google Sign-In.

  1. Dans la console Firebase, développez le menu Build (Créer) dans le panneau de gauche.
  2. Cliquez sur Authentification, puis sur le bouton Commencer, puis sur l'onglet Mode de connexion (ou cliquez ici pour accéder directement à l'onglet Mode de connexion).
  3. Cliquez sur Adresse e-mail/Mot de passe dans la liste Fournisseurs de connexion, activez l'option Activer, puis cliquez sur Enregistrer. 58e3e3e23c2f16a4.png

3. Configurer l'application Flutter

Avant de commencer, vous devez télécharger le code de démarrage et installer la CLI Firebase.

Télécharger le code de démarrage

Clonez le dépôt GitHub à partir de la ligne de commande :

git clone https://github.com/flutter/codelabs.git flutter-codelabs

Si l'outil CLI GitHub est installé sur votre ordinateur, procédez comme suit:

gh repo clone flutter/codelabs flutter-codelabs

L'exemple de code doit être cloné dans le répertoire flutter-codelabs de votre ordinateur, qui contient le code d'un ensemble d'ateliers de programmation. Le code de cet atelier de programmation se trouve dans le sous-répertoire flutter-codelabs/firebase-auth-flutterfire-ui.

Le répertoire flutter-codelabs/firebase-auth-flutterfire-ui contient deux projets Flutter. L'une est appelée complete et l'autre start. Le répertoire start contient un projet incomplet, et c'est là que vous passerez le plus de temps.

cd flutter-codelabs/firebase-auth-flutterfire-ui/start

Si vous souhaitez passer à l'étape suivante ou voir à quoi doit ressembler un élément une fois terminé, consultez le répertoire nommé "complete" pour effectuer une comparaison.

Si vous souhaitez suivre l'atelier de programmation et ajouter du code vous-même, commencez par l'application Flutter à l'emplacement flutter-codelabs/firebase-auth-flutterfire-ui/start, puis ajoutez du code à ce projet tout au long de l'atelier. Ouvrez ou importez ce répertoire dans l'IDE de votre choix.

Installer la CLI Firebase

La CLI Firebase fournit des outils pour gérer vos projets Firebase. La CLI est requise pour la CLI FlutterFire, que vous installerez dans quelques instants.

Il existe plusieurs façons d'installer la CLI. Le moyen le plus simple, si vous utilisez macOS ou Linux, consiste à exécuter cette commande à partir de votre terminal:

curl -sL https://firebase.tools | bash

Après avoir installé la CLI, vous devez vous authentifier auprès de Firebase.

  1. Exécutez la commande suivante pour vous connecter à Firebase avec votre compte Google :
firebase login
  1. Cette commande connecte votre machine locale à Firebase et vous permet d'accéder à vos projets Firebase.
  1. Vérifiez que la CLI est correctement installée et qu'elle a accès à votre compte en listant vos projets Firebase. Exécutez la commande suivante :
firebase projects:list
  1. La liste affichée doit être identique à celle des projets Firebase listés dans la console Firebase. Vous devriez voir au moins flutterfire-ui-codelab.

Installer la CLI FlutterFire

La CLI FlutterFire est un outil qui facilite l'installation de Firebase sur toutes les plates-formes compatibles de votre application Flutter. Elle est basée sur la CLI Firebase.

Commencez par installer la CLI:

dart pub global activate flutterfire_cli

Assurez-vous que la CLI a été installée. Exécutez la commande suivante et assurez-vous que la CLI affiche le menu d'aide.

flutterfire -—help

Ajouter votre projet Firebase à votre application Flutter

Configurer FlutterFire

Vous pouvez utiliser FlutterFire pour générer le code Dart nécessaire à l'utilisation de Firebase dans votre application Flutter.

flutterfire configure

Lorsque vous exécutez cette commande, vous êtes invité à sélectionner le projet Firebase que vous souhaitez utiliser et les plates-formes que vous souhaitez configurer.

Les captures d'écran suivantes montrent les requêtes auxquelles vous devrez répondre.

  1. Sélectionnez le projet que vous souhaitez utiliser. Dans ce cas, utilisez flutterfire-ui-codelab 1359cdeb83204baa.png.
  2. Sélectionnez les plates-formes que vous souhaitez utiliser. Dans cet atelier de programmation, vous allez configurer l'authentification Firebase pour Flutter pour le Web, iOS et Android. Vous pouvez toutefois configurer votre projet Firebase pour utiliser toutes les options. 301c9534f594f472.png
  3. Cette capture d'écran montre le résultat à la fin du processus. Si vous connaissez bien Firebase, vous remarquerez que vous n'avez pas eu à créer d'applications de plate-forme (par exemple, une application Android) dans la console. La CLI FlutterFire l'a fait pour vous. 12199a85ade30459.png

Une fois cette opération terminée, examinez l'application Flutter dans votre éditeur de texte. La CLI FlutterFire a généré un nouveau fichier appelé firebase_options.dart. Ce fichier contient une classe appelée FirebaseOptions, qui comporte des variables statiques contenant la configuration Firebase requise pour chaque plate-forme. Si vous avez sélectionné toutes les plates-formes lorsque vous avez exécuté flutterfire configure, vous verrez des valeurs statiques nommées web, android, ios et macos.

firebase_options.dart.

import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
   show defaultTargetPlatform, kIsWeb, TargetPlatform;

/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// import 'firebase_options.dart';
/// // ...
/// await Firebase.initializeApp(
///   options: DefaultFirebaseOptions.currentPlatform,
/// );
/// ```
class DefaultFirebaseOptions {
 static FirebaseOptions get currentPlatform {
   if (kIsWeb) {
     return web;
   }
   // ignore: missing_enum_constant_in_switch
   switch (defaultTargetPlatform) {
     case TargetPlatform.android:
       return android;
     case TargetPlatform.iOS:
       return ios;
     case TargetPlatform.macOS:
       return macos;
   }

   throw UnsupportedError(
     'DefaultFirebaseOptions are not supported for this platform.',
   );
 }

 static const FirebaseOptions web = FirebaseOptions(
   apiKey: 'AIzaSyCqFjCV_9CZmYeIvcK9FVy4drmKUlSaIWY',
   appId: '1:963656261848:web:7219f7fca5fc70afb237ad',
   messagingSenderId: '963656261848',
   projectId: 'flutterfire-ui-codelab',
   authDomain: 'flutterfire-ui-codelab.firebaseapp.com',
   storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
   measurementId: 'G-DGF0CP099H',
 );

 static const FirebaseOptions android = FirebaseOptions(
   apiKey: 'AIzaSyDconZaCQpkxIJ5KQBF-3tEU0rxYsLkIe8',
   appId: '1:963656261848:android:c939ccc86ab2dcdbb237ad',
   messagingSenderId: '963656261848',
   projectId: 'flutterfire-ui-codelab',
   storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
 );

 static const FirebaseOptions ios = FirebaseOptions(
   apiKey: 'AIzaSyBqLWsqFjYAdGyihKTahMRDQMo0N6NVjAs',
   appId: '1:963656261848:ios:d9e01cfe8b675dfcb237ad',
   messagingSenderId: '963656261848',
   projectId: 'flutterfire-ui-codelab',
   storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
   iosClientId: '963656261848-v7r3vq1v6haupv0l1mdrmsf56ktnua60.apps.googleusercontent.com',
   iosBundleId: 'com.example.complete',
 );

 static const FirebaseOptions macos = FirebaseOptions(
   apiKey: 'AIzaSyBqLWsqFjYAdGyihKTahMRDQMo0N6NVjAs',
   appId: '1:963656261848:ios:d9e01cfe8b675dfcb237ad',
   messagingSenderId: '963656261848',
   projectId: 'flutterfire-ui-codelab',
   storageBucket: 'flutterfire-ui-codelab.firebasestorage.app',
   iosClientId: '963656261848-v7r3vq1v6haupv0l1mdrmsf56ktnua60.apps.googleusercontent.com',
   iosBundleId: 'com.example.complete',
 );
}

Firebase utilise le mot "application" pour désigner une compilation spécifique pour une plate-forme spécifique dans un projet Firebase. Par exemple, le projet Firebase appelé FlutterFire-ui-codelab contient plusieurs applications : une pour Android, une pour iOS, une pour macOS et une pour le Web.

La méthode DefaultFirebaseOptions.currentPlatform utilise l'énumération TargetPlatform exposée par Flutter pour détecter la plate-forme sur laquelle votre application s'exécute, puis renvoie les valeurs de configuration Firebase nécessaires pour l'application Firebase appropriée.

Ajouter des packages Firebase à l'application Flutter

La dernière étape de configuration consiste à ajouter les packages Firebase pertinents à votre projet Flutter. Le fichier firebase_options.dart devrait contenir des erreurs, car il repose sur des packages Firebase qui n'ont pas encore été ajoutés. Dans le terminal, assurez-vous d'être dans la racine du projet Flutter à l'emplacement flutter-codelabs/firebase-emulator-suite/start. Exécutez ensuite les trois commandes suivantes :

flutter pub add firebase_core
flutter pub add firebase_auth
flutter pub add firebase_ui_auth

Ce sont les seuls packages dont vous avez besoin pour le moment.

Initialiser Firebase

Pour utiliser les packages ajoutés et DefaultFirebaseOptions.currentPlatform,, mettez à jour le code dans la fonction main du fichier main.dart.

main.dart

void main() async {
 WidgetsFlutterBinding.ensureInitialized();
 await Firebase.initializeApp(
   options: DefaultFirebaseOptions.currentPlatform,
 );


 runApp(const MyApp());
}

Ce code remplit deux fonctions.

  1. WidgetsFlutterBinding.ensureInitialized() indique à Flutter de ne pas commencer à exécuter le code du widget de l'application tant que le framework Flutter n'est pas complètement démarré. Firebase utilise des canaux de plate-forme natifs, qui nécessitent que le framework soit en cours d'exécution.
  2. Firebase.initializeApp configure une connexion entre votre application Flutter et votre projet Firebase. Le DefaultFirebaseOptions.currentPlatform est importé à partir de notre fichier firebase_options.dart généré. Cette valeur statique détecte la plate-forme sur laquelle vous exécutez l'application et transmet les clés Firebase correspondantes.

4. Ajouter la page d'authentification de l'UI Firebase initiale

L'interface utilisateur de Firebase pour Auth fournit des widgets qui représentent des écrans entiers de votre application. Ces écrans gèrent différents flux d'authentification dans votre application, tels que la connexion, l'enregistrement, l'oubli de mot de passe, le profil utilisateur, etc. Pour commencer, ajoutez une page de destination à votre application qui sert de pare-feu d'authentification à l'application principale.

Application Material ou Cupertino

L'UI FlutterFire exige que votre application soit encapsulée dans MaterialApp ou CupertinoApp. En fonction de votre choix, l'interface utilisateur reflètera automatiquement les différences entre les widgets Material et Cupertino. Pour cet atelier de programmation, utilisez MaterialApp, qui est déjà ajouté à l'application dans app.dart.

app.dart

import 'package:flutter/material.dart';
import 'auth_gate.dart';

class MyApp extends StatelessWidget {
 const MyApp({super.key});
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     theme: ThemeData(
       primarySwatch: Colors.blue,
     ),
     home: const AuthGate(),
   );
 }
}

Vérifier l'état de l'authentification

Avant de pouvoir afficher un écran de connexion, vous devez déterminer si l'utilisateur est actuellement authentifié. Le moyen le plus courant de vérifier cela consiste à écouter les authStateChanges de FirebaseAuth à l'aide du plug-in Firebase Authentication.

Dans l'exemple de code ci-dessus, MaterialApp crée un widget AuthGate dans sa méthode de compilation. (Il s'agit d'un widget personnalisé, qui n'est pas fourni par l'UI FlutterFire.)

Ce widget doit être mis à jour pour inclure le flux authStateChanges.

L'API authStateChanges renvoie un Stream avec l'utilisateur actuel (s'il est connecté) ou la valeur "null" s'il ne l'est pas. Pour vous abonner à cet état dans notre application, vous pouvez utiliser le widget StreamBuilder de Flutter et lui transmettre le flux.

StreamBuilder est un widget qui se crée en fonction du dernier instantané des données d'un flux que vous lui transmettez. Il est automatiquement reconstruit lorsque le flux émet un nouvel instantané.

Mettez à jour le code dans auth_gate.dart.

auth_gate.dart.

import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

import 'home.dart';

class AuthGate extends StatelessWidget {
  const AuthGate({super.key});

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<User?>(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          return SignInScreen(
            providers: [],
          );
        }

        return const HomeScreen();
      },
    );
  }
}
  • StreamBuilder.stream transmet FirebaseAuth.instance.authStateChanged, le flux mentionné précédemment, qui renvoie un objet User Firebase si l'utilisateur s'est authentifié. (Sinon, elle renvoie null.)
  • Ensuite, le code utilise snapshot.hasData pour vérifier si la valeur du flux contient l'objet User.
  • Si ce n'est pas le cas, un widget SignInScreen est renvoyé. Pour le moment, cet écran ne sert à rien. Ce paramètre sera mis à jour à l'étape suivante.
  • Sinon, il renvoie HomeScreen, qui est la partie principale de l'application à laquelle seuls les utilisateurs authentifiés peuvent accéder.

SignInScreen est un widget provenant du package d'interface utilisateur FlutterFire. Ce sera l'objet de la prochaine étape de cet atelier de programmation. À ce stade, lorsque vous exécutez l'application, un écran de connexion vide doit s'afficher.

5. Écran de connexion

Le widget SignInScreen, fourni par l'interface utilisateur FlutterFire, ajoute les fonctionnalités suivantes:

  • Permet aux utilisateurs de se connecter
  • Si les utilisateurs ont oublié leur mot de passe, ils peuvent appuyer sur "Mot de passe oublié ?" et être redirigés vers un formulaire permettant de réinitialiser leur mot de passe.
  • Si un utilisateur n'est pas encore inscrit, il peut appuyer sur "S'inscrire" et accéder à un autre formulaire lui permettant de s'inscrire.

Encore une fois, cela ne nécessite que quelques lignes de code. Rappelez-vous le code dans le widget AuthGate :

auth_gate.dart

import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

import 'home.dart';

class AuthGate extends StatelessWidget {
  const AuthGate({super.key});

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<User?>(
      stream: FirebaseAuth.instance.authStateChanges(),
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          return SignInScreen(
            providers: [
              EmailAuthProvider(), // new
            ],
          );
        }

        return const HomeScreen();
      },
    );
  }
}

Le widget SignInScreen et son argument providers sont le seul code requis pour obtenir toutes les fonctionnalités mentionnées ci-dessus. Vous devriez maintenant voir un écran de connexion avec les entrées de texte "Adresse e-mail" et "Mot de passe", ainsi qu'un bouton "Connexion".

Bien que fonctionnel, il manque de style. Le widget expose des paramètres permettant de personnaliser l'apparence de l'écran de connexion. Par exemple, vous pouvez ajouter le logo de votre entreprise.

Personnaliser l'écran de connexion

headerBuilder

À l'aide de l'argument SignInScreen.headerBuilder, vous pouvez ajouter les widgets de votre choix au-dessus du formulaire de connexion. Ce widget ne s'affiche que sur les écrans étroits, comme les appareils mobiles. Sur les grands écrans, vous pouvez utiliser SignInScreen.sideBuilder, qui est abordé plus loin dans cet atelier de programmation.

Mettez à jour le fichier auth_gate.dart avec le code suivant:

auth_gate.dart.

import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

import 'home.dart';

class AuthGate extends StatelessWidget {
 const AuthGate({super.key});

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider(),
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('assets/flutterfire_300x.png'),
               ),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }
}

L'argument headerBuilder nécessite une fonction de type HeaderBuilder, qui est définie dans le package d'UI FlutterFire.

typedef HeaderBuilder = Widget Function(
 BuildContext context,
 BoxConstraints constraints,
 double shrinkOffset,
);

Comme il s'agit d'un rappel, il expose les valeurs que vous pouvez utiliser, telles que BuildContext et BoxConstraints, et vous oblige à renvoyer un widget. Le widget que vous renvoyez s'affiche en haut de l'écran. Dans cet exemple, le nouveau code ajoute une image en haut de l'écran. Votre application devrait maintenant se présenter comme suit.

73d7548d91bbd2ab.png

Outil de création de sous-titres

L'écran de connexion expose trois paramètres supplémentaires qui vous permettent de le personnaliser : subtitleBuilder, footerBuilder et sideBuilder.

subtitleBuilder est légèrement différent, car les arguments de rappel incluent une action, qui est de type AuthAction. AuthAction est une énumération qui permet de détecter si l'écran de connexion ou d'inscription de l'utilisateur est celui sur lequel se trouve l'utilisateur.

Mettez à jour le code dans auth_gate.dart pour utiliser subtitleBuilder.

auth_gate.dart.

import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

import 'home.dart';

class AuthGate extends StatelessWidget {
 const AuthGate({super.key});

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
              EmailAuthProvider()
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }
}

Actualisez l'application. Elle doit se présenter comme suit :

L'argument footerBuilder est identique à celui de subtitleBuilder. Il n'expose pas BoxConstraints ni shrinkOffset, car il est destiné au texte plutôt qu'aux images. (Vous pouvez cependant ajouter le widget de votre choix.)

Ajoutez un pied de page à votre écran de connexion à l'aide de ce code.

auth_gate.dart

import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

import 'home.dart';

class AuthGate extends StatelessWidget {
 const AuthGate({super.key});

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider()
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
           footerBuilder: (context, action) {
             return const Padding(
               padding: EdgeInsets.only(top: 16),
               child: Text(
                 'By signing in, you agree to our terms and conditions.',
                 style: TextStyle(color: Colors.grey),
               ),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }}

Side Builder

L'argument SignInScreen.sidebuilder accepte un rappel, mais cette fois, les arguments de ce rappel sont BuildContext et double shrinkOffset. Le widget renvoyé par sideBuilder s'affiche à gauche du formulaire de connexion, et uniquement sur les écrans larges. Cela signifie que le widget ne s'affichera que dans les applications Web et de bureau.

En interne, l'interface utilisateur FlutterFire utilise un point d'arrêt pour déterminer si le contenu de l'en-tête doit s'afficher (sur les grands écrans, comme les mobiles) ou si le contenu latéral doit s'afficher (sur les grands écrans, les ordinateurs ou le Web). Plus précisément, si la largeur d'un écran est supérieure à 800 pixels, le contenu du générateur de côté s'affiche, mais pas celui de l'en-tête. Si la largeur de l'écran est inférieure à 800 pixels, c'est le contraire qui se produit.

Mettez à jour le code dans auth_gate.dart pour ajouter des widgets sideBuilder.

auth_gate.dart

import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

import 'home.dart';

class AuthGate extends StatelessWidget {
 const AuthGate({super.key});

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider(),
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
           footerBuilder: (context, action) {
             return const Padding(
               padding: EdgeInsets.only(top: 16),
               child: Text(
                 'By signing in, you agree to our terms and conditions.',
                 style: TextStyle(color: Colors.grey),
               ),
             );
           },
           sideBuilder: (context, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
         );
       }
       return const HomeScreen();
     },
   );
 }
}

Votre application devrait maintenant se présenter comme suit lorsque vous développez la largeur de la fenêtre (si vous utilisez Flutter pour le Web ou macOS).

8dc60b4e5d7dd2d0.png

Créer un compte utilisateur

À ce stade, tout le code de cet écran est terminé. Toutefois, avant de pouvoir vous connecter, vous devez créer un utilisateur. Vous pouvez le faire à l'aide de l'écran "S'inscrire" ou créer un utilisateur dans la console Firebase.

Pour utiliser la console, procédez comme suit :

  1. Accédez au tableau "Utilisateurs" dans la console Firebase.
  2. Cliquez ici
  3. Sélectionnez "flutterfire-ui-codelab" (ou un autre projet si vous avez utilisé un autre nom). Le tableau suivant s'affiche:

f038fd9a58ed60d9.png

  1. Cliquez sur le bouton "Ajouter un utilisateur".

2d78390d4c5dbbfa.png

  1. Saisissez une adresse e-mail et un mot de passe pour le nouvel utilisateur. Il peut s'agir d'une adresse e-mail et d'un mot de passe factices, comme je l'ai indiqué dans l'image ci-dessous. Cela fonctionnera, mais la fonctionnalité "Mot de passe oublié" ne fonctionnera pas si vous utilisez une fausse adresse e-mail.

62ba0feb33d54add.png

  1. Cliquez sur "Ajouter un utilisateur"

32b236b3ef94d4c7.png

Vous pouvez maintenant revenir à votre application Flutter et connecter un utilisateur via la page de connexion. Votre application devrait se présenter comme suit:

DD43d260537f3b1a.png

6. Écran du profil

L'interface utilisateur FlutterFire fournit également un widget ProfileScreen qui vous offre de nombreuses fonctionnalités en quelques lignes de code.

Ajouter le widget ProfileScreen

Accédez au fichier home.dart dans votre éditeur de texte. Mettez-la à jour avec le code suivant:

home.dart

import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: [
          IconButton(
            icon: const Icon(Icons.person),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute<ProfileScreen>(
                  builder: (context) => const ProfileScreen(),
                ),
              );
            },
          )
        ],
        automaticallyImplyLeading: false,
      ),
      body: Center(
        child: Column(
          children: [
            Image.asset('dash.png'),
            Text(
              'Welcome!',
              style: Theme.of(context).textTheme.displaySmall,
            ),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

Le nouveau code de note est le rappel transmis à IconButton.isPressed method.. Lorsque vous appuyez sur ce bouton IconButton, votre application crée une route anonyme et y accède. Cette route affichera le widget ProfileScreen, renvoyé par le rappel MaterialPageRoute.builder.

Actualisez votre application et appuyez sur l'icône située en haut à droite (dans la barre d'application) pour afficher une page semblable à celle-ci:

36487fc4ab4f26a7.png

Il s'agit de l'UI standard fournie par la page de l'UI FlutterFire. Tous les boutons et champs de texte sont connectés à Firebase Auth et fonctionnent immédiatement. Par exemple, vous pouvez saisir un nom dans le champ de texte "Name" (Nom). L'interface utilisateur FlutterFire appellera la méthode FirebaseAuth.instance.currentUser?.updateDisplayName, qui enregistrera ce nom dans Firebase.

Se déconnecter

Pour le moment, si vous appuyez sur le bouton "Se déconnecter", l'application ne change pas. Vous serez déconnecté, mais vous ne serez pas redirigé vers le widget AuthGate. Pour ce faire, utilisez le paramètre ProfileScreen.actions.

Commencez par mettre à jour le code dans home.dart.

home.dart

import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: [
          IconButton(
            icon: const Icon(Icons.person),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute<ProfileScreen>(
                  builder: (context) => ProfileScreen(
                    actions: [
                      SignedOutAction((context) {
                        Navigator.of(context).pop();
                      })
                    ],
                  ),
                ),
              );
            },
          )
        ],
        automaticallyImplyLeading: false,
      ),
      body: Center(
        child: Column(
          children: [
            Image.asset('dash.png'),
            Text(
              'Welcome!',
              style: Theme.of(context).textTheme.displaySmall,
            ),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

Désormais, lorsque vous créez une instance de ProfileScreen, vous lui transmettez également une liste d'actions à l'argument ProfileScreen.actions. Ces actions sont du type FlutterFireUiAction. De nombreuses classes sont des sous-types de FlutterFireUiAction. En général, vous les utilisez pour indiquer à votre application de réagir à différents changements d'état d'authentification. SignedOutAction appelle une fonction de rappel que vous lui attribuez lorsque l'état d'authentification Firebase passe à currentUser ayant la valeur null.

En ajoutant un rappel qui appelle Navigator.of(context).pop() lorsque SignedOutAction se déclenche, l'application accède à la page précédente. Dans cet exemple d'application, il n'existe qu'un seul parcours permanent, qui affiche la page de connexion si aucun utilisateur n'est connecté et la page d'accueil s'il y en a un. Étant donné que cela se produit lorsque l'utilisateur se déconnecte, l'application affiche la page de connexion.

Personnaliser la page de profil

Comme la page de connexion, la page de profil est personnalisable. Tout d'abord, notre page actuelle ne permet pas de revenir à la page d'accueil une fois qu'un utilisateur est sur la page de profil. Pour résoudre ce problème, attribuez une barre d'application au widget ProfileScreen.

home.dart

import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
 const HomeScreen({super.key});

 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(
       actions: [
         IconButton(
           icon: const Icon(Icons.person),
           onPressed: () {
             Navigator.push(
               context,
               MaterialPageRoute<ProfileScreen>(
                 builder: (context) => ProfileScreen(
                   appBar: AppBar(
                     title: const Text('User Profile'),
                   ),
                   actions: [
                     SignedOutAction((context) {
                       Navigator.of(context).pop();
                     })
                   ],
                 ),
               ),
             );
           },
         )
       ],
       automaticallyImplyLeading: false,
     ),
     body: Center(
       child: Column(
         children: [
           Image.asset('dash.png'),
           Text(
             'Welcome!',
             style: Theme.of(context).textTheme.displaySmall,
           ),
           const SignOutButton(),
         ],
       ),
     ),
   );
 }
}

L'argument ProfileScreen.appBar accepte un widget AppBar du package Material Flutter. Il peut donc être traité comme tout autre AppBar que vous avez créé et transmis à un Scaffold. Dans cet exemple, la fonctionnalité par défaut consistant à ajouter automatiquement un bouton "Retour" est conservée, et l'écran dispose désormais d'un titre.

Ajouter des enfants à l'écran de profil

Le widget ProfileScreen comporte également un argument facultatif nommé "children". Cet argument accepte une liste de widgets, qui seront placés verticalement à l'intérieur d'un widget de colonne déjà utilisé en interne pour créer ProfileScreen. Ce widget de colonne dans la méthode de compilation ProfileScreen placera les enfants que vous le transmettez au-dessus du bouton "Sign out" (Déconnexion).

Mettez à jour le code dans home.dart pour afficher le logo de l'entreprise ici, comme sur l'écran de connexion.

home.dart

import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: [
          IconButton(
            icon: const Icon(Icons.person),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute<ProfileScreen>(
                  builder: (context) => ProfileScreen(
                    appBar: AppBar(
                      title: const Text('User Profile'),
                    ),
                    actions: [
                      SignedOutAction((context) {
                        Navigator.of(context).pop();
                      })
                    ],
                    children: [
                      const Divider(),
                      Padding(
                        padding: const EdgeInsets.all(2),
                        child: AspectRatio(
                          aspectRatio: 1,
                          child: Image.asset('flutterfire_300x.png'),
                        ),
                      ),
                    ],
                  ),
                ),
              );
            },
          )
        ],
        automaticallyImplyLeading: false,
      ),
      body: Center(
        child: Column(
          children: [
            Image.asset('dash.png'),
            Text(
              'Welcome!',
              style: Theme.of(context).textTheme.displaySmall,
            ),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

Actualisez l'application. Le message suivant s'affiche à l'écran:

Ebe5792b765dbf87.png

7. Connexion avec l'authentification multiplate-forme de Google

L'interface utilisateur FlutterFire fournit également des widgets et des fonctionnalités pour l'authentification auprès de fournisseurs tiers, tels que Google, Twitter, Facebook, Apple et GitHub.

Pour intégrer l'authentification Google, installez le plug-in officiel firebase_ui_oauth_google et ses dépendances, qui géreront le flux d'authentification natif. Dans le terminal, accédez à la racine de votre projet Flutter, puis saisissez la commande suivante :

flutter pub add google_sign_in
flutter pub add firebase_ui_oauth_google

Activer le fournisseur de connexion Google

Ensuite, activez le fournisseur Google dans la console Firebase:

  1. Accédez à l'écran Fournisseurs de connexion via l'authentification dans la console.
  2. Cliquez sur "Ajouter un fournisseur". 8286fb28be94bf30.png
  3. Sélectionnez "Google". c4e28e6f4974be7f.png
  4. Activez le bouton bascule "Enable" (Activer), puis appuyez sur "Save" (Enregistrer). E74ff86990763826.png
  5. Si une fenêtre modale s'affiche avec des informations sur le téléchargement des fichiers de configuration, cliquez sur "OK".
  6. Vérifiez que le fournisseur de connexion Google a été ajouté. 5329ce0543c90d95.png

Ajouter un bouton de connexion Google

Lorsque Google Sign-In est activé, ajoutez le widget nécessaire pour afficher un bouton Google Sign-In stylisé sur la page de connexion. Accédez au fichier auth_gate.dart et modifiez le code comme suit:

auth_gate.dart

import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:firebase_ui_oauth_google/firebase_ui_oauth_google.dart'; // new
import 'package:flutter/material.dart';

import 'home.dart';

class AuthGate extends StatelessWidget {
 const AuthGate({super.key});

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider(),
             GoogleProvider(clientId: "YOUR_WEBCLIENT_ID"),  // new
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
           footerBuilder: (context, action) {
             return const Padding(
               padding: EdgeInsets.only(top: 16),
               child: Text(
                 'By signing in, you agree to our terms and conditions.',
                 style: TextStyle(color: Colors.grey),
               ),
             );
           },
           sideBuilder: (context, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }
}

Le seul code nouveau ici est l'ajout de GoogleProvider(clientId: "YOUR_WEBCLIENT_ID") à la configuration du widget SignInScreen.

Ensuite, actualisez votre application. Un bouton de connexion Google s'affiche.

Aca71a46a011bfb5.png

Bouton de configuration de la connexion

Le bouton ne fonctionne pas sans configuration supplémentaire. Si vous développez avec Flutter pour le Web, il s'agit de la seule étape que vous devez ajouter pour que cela fonctionne. D'autres plates-formes nécessitent des étapes supplémentaires, que nous allons aborder plus tard.

  1. Accédez à la page "Fournisseurs d'authentification" dans la console Firebase.
  2. Cliquez sur le fournisseur Google. 9b3a325c5eca6e49.png
  3. Cliquez sur le panneau d'expansion "Configuration du SDK Web".
  4. Copiez la valeur indiquée dans "ID client Web" 711a79f0d931c60f.png.
  5. Revenez à votre éditeur de texte et mettez à jour l'instance de GoogleProvider dans le fichier auth_gate.dart en transmettant cet ID au paramètre nommé clientId.
GoogleProvider(
   clientId: "YOUR_WEBCLIENT_ID"
)

Une fois l'ID client Web saisi, actualisez votre application. Lorsque vous appuyez sur le bouton "Se connecter avec Google", une nouvelle fenêtre s'affiche (si vous utilisez le Web) qui vous guide tout au long du processus de connexion Google. Au début, il se présente comme suit :

14e73e3c9de704bb.png

Configurer iOS

Pour que cela fonctionne sur iOS, un processus de configuration supplémentaire est nécessaire.

  1. Accédez à l'écran "Paramètres du projet" dans la console Firebase. Une fiche présentant vos applications Firebase s'affiche alors: fefa674acbf213cc.png
  2. Cliquez sur iOS. Notez que le nom de votre application sera différent du mien. Là où le mien indique "complete" (Terminé), le vôtre indiquera "start" (Démarrer), si vous avez utilisé le projet flutter-codelabs/firebase-auth-flutterfire-ui/start pour suivre cet atelier de programmation.
  3. Cliquez sur le bouton "GoogleServices-Info.plist" pour télécharger le fichier de configuration nécessaire. f89b3192871dfbe3.png
  4. Glissez-déposez le fichier téléchargé dans le répertoire appelé ./ios/Runner dans votre projet Flutter.
  5. Ouvrez Xcode en exécutant la commande de terminal suivante depuis la racine de votre projet: open ios/Runner.xcworkspace
  6. Effectuez un clic droit sur le répertoire "Runner" et sélectionnez "Add Files to "Runner" (Ajouter des fichiers à "Runner"). 858986063a4c5201.png
  7. Sélectionnez GoogleService-Info.plist dans le gestionnaire de fichiers.
  8. Dans votre éditeur de texte (qui n'est pas Xcode), ajoutez les attributs CFBundleURLTypes ci-dessous dans le fichier [my_project]/ios/Runner/Info.plist.
<!-- Put me in the [my_project]/ios/Runner/Info.plist file -->
<!-- Google Sign-in Section -->
<key>CFBundleURLTypes</key>
<array>
        <dict>
                <key>CFBundleTypeRole</key>
                <string>Editor</string>
                <key>CFBundleURLSchemes</key>
                <array>
                        <!-- TODO Replace this value: -->
                        <!-- Copied from GoogleService-Info.plist key REVERSED_CLIENT_ID -->
                        <string>com.googleusercontent.apps.861823949799-vc35cprkp249096uujjn0vvnmcvjppkn</string>
                </array>
        </dict>
</array>
<!-- End of the Google Sign-in Section -->
  1. Vous devez remplacer le GoogleProvider.clientId que vous avez ajouté dans la configuration Web par l'ID client associé à votre ID client Firebase pour iOS. Vous pouvez trouver cet ID dans le fichier firebase_options.dart, avec la constante iOS. Copiez la valeur transmise à iOSClientId.
static const FirebaseOptions ios = FirebaseOptions(
  apiKey: 'YOUR API KEY',
  appId: 'YOUR APP ID',
  messagingSenderId: '',
  projectId: 'PROJECT_ID',
  storageBucket: 'PROJECT_ID.firebasestorage.app',
  iosClientId: 'IOS CLIENT ID', // Find your iOS client Id here.
  iosBundleId: 'com.example.BUNDLE',
);
  1. Collez cette valeur dans l'argument GoogleProvider.clientId du widget AuthGate.
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:firebase_ui_oauth_google/firebase_ui_oauth_google.dart';
import 'package:flutter/material.dart';

import 'home.dart';


class AuthGate extends StatelessWidget {
 const AuthGate({super.key});

 @override
 Widget build(BuildContext context) {
   return StreamBuilder<User?>(
     stream: FirebaseAuth.instance.authStateChanges(),
     builder: (context, snapshot) {
       if (!snapshot.hasData) {
         return SignInScreen(
           providers: [
             EmailAuthProvider(),
             GoogleProvider(clientId: "YOUR IOS CLIENT ID"),  // replace String
           ],
           headerBuilder: (context, constraints, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
           subtitleBuilder: (context, action) {
             return Padding(
               padding: const EdgeInsets.symmetric(vertical: 8.0),
               child: action == AuthAction.signIn
                   ? const Text('Welcome to FlutterFire, please sign in!')
                   : const Text('Welcome to Flutterfire, please sign up!'),
             );
           },
           footerBuilder: (context, action) {
             return const Padding(
               padding: EdgeInsets.only(top: 16),
               child: Text(
                 'By signing in, you agree to our terms and conditions.',
                 style: TextStyle(color: Colors.grey),
               ),
             );
           },
           sideBuilder: (context, shrinkOffset) {
             return Padding(
               padding: const EdgeInsets.all(20),
               child: AspectRatio(
                 aspectRatio: 1,
                 child: Image.asset('flutterfire_300x.png'),
               ),
             );
           },
         );
       }

       return const HomeScreen();
     },
   );
 }
}

Si votre application Flutter s'exécute déjà sous iOS, vous devez l'arrêter complètement, puis la réexécuter. Sinon, exécutez l'application sur iOS.

8. Félicitations !

Vous avez terminé l'atelier de programmation sur l'UI Firebase Auth pour Flutter. Vous trouverez le code final de cet atelier de programmation dans le répertoire "complete" sur GitHub : Ateliers de programmation Flutter.

Points abordés

  • Configurer une application Flutter pour utiliser Firebase
  • Configurer un projet Firebase dans la console Firebase
  • CLI FlutterFire
  • CLI Firebase
  • Utiliser Firebase Authentication
  • Utiliser l'interface utilisateur FlutterFire pour gérer facilement l'authentification Firebase dans votre application Flutter

Étapes suivantes

En savoir plus

Sparky est là pour fêter ça avec vous !

2a0ad195769368b1.gif