Adicione um fluxo de autenticação de usuário a um aplicativo Flutter usando FirebaseUI

1. Antes de começar

Neste codelab, você aprenderá como adicionar o Firebase Authentication ao seu aplicativo Flutter usando o pacote de IU do FlutterFire. Com este pacote, você adicionará autenticação de e-mail/senha e autenticação de login do Google a um aplicativo Flutter. Você também aprenderá como configurar um projeto do Firebase e usar a CLI do FlutterFire para inicializar o Firebase em seu aplicativo Flutter.

Pré-requisitos

Este codelab pressupõe que você tenha alguma experiência com Flutter. Caso contrário, você pode querer primeiro aprender o básico. Os seguintes links são úteis:

Você também deve ter alguma experiência com Firebase, mas está tudo bem se você nunca adicionou o Firebase a um projeto Flutter. Se você não está familiarizado com o console do Firebase ou é completamente novo no Firebase, consulte primeiro os seguintes links:

O que você criará

Este codelab orienta você na criação do fluxo de autenticação para um aplicativo Flutter usando o Firebase for Authentication. O aplicativo terá uma tela de login, uma tela de ‘Cadastro’, uma tela de recuperação de senha e uma tela de perfil de usuário.

6604fc9157f2c6ae.pngeab9509a41074930.pngda49189a5838e0bb.pngb2ccfb3632b77878.png

O que você aprenderá

Este codelab abrange:

  • Adicionando Firebase a um aplicativo Flutter
  • Configuração do Console do Firebase
  • Usando Firebase CLI para adicionar Firebase ao seu aplicativo
  • Usando FlutterFire CLI para gerar configuração do Firebase no Dart
  • Adicionando Firebase Authentication ao seu aplicativo Flutter
  • Configuração do Firebase Authentication no console
  • Adicionando login de e-mail e senha com o pacote firebase_ui_auth
  • Adicionando registro de usuário com o pacote firebase_ui_auth
  • Adicionando uma mensagem 'Esqueceu a senha?' página
  • Adicionando login do Google com firebase_ui_auth
  • Configurando seu aplicativo para funcionar com vários provedores de login.
  • Adicionando uma tela de perfil de usuário ao seu aplicativo com o pacote firebase_ui_auth

Este codelab se preocupa especificamente em adicionar um sistema de autenticação robusto usando o pacote firebase_ui_auth . Como você verá, todo esse aplicativo, com todos os recursos acima, pode ser implementado com cerca de 100 linhas de código.

O que você precisará

  • Conhecimento prático de Flutter e do SDK instalado
  • Um editor de texto (JetBrains IDE, Android Studio e VS Code são suportados pelo Flutter)
  • Navegador Google Chrome ou outro alvo de desenvolvimento preferido para Flutter. (Alguns comandos de terminal neste codelab presumirão que você está executando seu app no ​​Chrome)

2. Crie e configure um projeto Firebase

A primeira tarefa que você precisará concluir é criar um projeto do Firebase no console da web do Firebase.

Crie um projeto do Firebase

  1. Faça login no Firebase .
  2. No console do Firebase, clique em Adicionar projeto (ou Criar um projeto ) e insira um nome para seu projeto do Firebase (por exemplo, " FlutterFire-UI-Codelab ").

df42a5e3d9584b48.png

  1. Clique nas opções de criação do projeto. Aceite os termos do Firebase, se solicitado. Ignore a configuração do Google Analytics porque você não usará o Analytics para este aplicativo.

d1fcec48bf251eaa.png

Para saber mais sobre os projetos do Firebase, consulte Entender os projetos do Firebase .

O aplicativo que você está criando usa o Firebase Authentication para permitir que os usuários façam login no aplicativo. Também permite que novos usuários se registrem no aplicativo Flutter.

O Firebase Authentication precisa ser ativado usando o Firebase Console e precisa de configuração especial depois de ativado.

Ativar login por e-mail para Firebase Authentication

Para permitir que os usuários façam login no aplicativo Web, primeiro você usará o método de login por e-mail/senha . Posteriormente, você adicionará o método de login do Google .

  1. No console do Firebase, expanda o menu Build no painel esquerdo.
  2. Clique em Autenticação e, em seguida, clique no botão Começar e, em seguida, na guia Método de login (ou clique aqui para ir diretamente para a guia Método de login ).
  3. Clique em E-mail/Senha na lista Provedores de login , defina o botão Ativar para a posição ativado e clique em Salvar . 58e3e3e23c2f16a4.png

3. Configure o aplicativo Flutter

Você precisará baixar o código inicial e instalar a CLI do Firebase antes de começarmos.

Obtenha o código inicial

Clone o repositório GitHub na linha de comando:

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

Como alternativa, se você tiver a ferramenta CLI do GitHub instalada:

gh repo clone flutter/codelabs flutter-codelabs

O código de amostra deve ser clonado no diretório flutter-codelabs da sua máquina, que contém o código de uma coleção de codelabs. O código deste codelab está no subdiretório flutter-codelabs/firebase-auth-flutterfire-ui .

O diretório flutter-codelabs/firebase-auth-flutterfire-ui contém dois projetos Flutter. Um é chamado de complete e o outro é chamado de start . O diretório start contém um projeto incompleto e é onde você passará a maior parte do tempo.

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

Se você quiser avançar ou ver como algo deve ficar quando concluído, procure no diretório chamado complete para referência cruzada.

Se quiser acompanhar o codelab e adicionar código você mesmo, comece com o aplicativo Flutter em flutter-codelabs/firebase-auth-flutterfire-ui/start e adicione código a esse projeto durante todo o codelab. Abra ou importe esse diretório para o seu IDE preferido.

Instale a CLI do Firebase

A Firebase CLI fornece ferramentas para gerenciar seus projetos do Firebase. A CLI é necessária para a CLI do FlutterFire, que você instalará em breve.

Existem várias maneiras de instalar a CLI. A maneira mais simples, se você estiver usando MacOS ou Linux, é executar este comando em seu terminal:

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

Depois de instalar a CLI, você deve se autenticar no Firebase.

  1. Faça login no Firebase usando sua conta do Google executando o seguinte comando:
firebase login
  1. Este comando conecta sua máquina local ao Firebase e concede acesso aos seus projetos do Firebase.
  1. Teste se a CLI está instalada corretamente e tem acesso à sua conta listando seus projetos do Firebase. Execute o seguinte comando:
firebase projects:list
  1. A lista exibida deve ser a mesma dos projetos do Firebase listados no console do Firebase . Você deve ver pelo menos flutterfire-ui-codelab.

Instale a CLI do FlutterFire

A CLI do FlutterFire é uma ferramenta que ajuda a facilitar o processo de instalação do Firebase em todas as plataformas suportadas em seu aplicativo Flutter. Ele foi desenvolvido com base na CLI do Firebase.

Primeiro, instale a CLI:

dart pub global activate flutterfire_cli

Certifique-se de que a CLI esteja instalada. Execute o comando a seguir e certifique-se de que a CLI gere o menu de ajuda.

flutterfire -—help

Adicione seu projeto do Firebase ao seu aplicativo Flutter

Configurar FlutterFire

Você pode usar o FlutterFire para gerar o código Dart necessário para usar o Firebase em seu aplicativo Flutter.

flutterfire configure

Quando este comando for executado, você será solicitado a selecionar qual projeto do Firebase deseja usar e quais plataformas deseja configurar.

As capturas de tela a seguir mostram os prompts que você precisará responder.

  1. Selecione o projeto que deseja usar. Neste caso, use flutterfire-ui-codelab 1359cdeb83204baa.png
  2. Selecione quais plataformas você deseja usar. Neste codelab, há etapas para configurar o Firebase Authentication for Flutter para Web, iOS e Android, mas você pode configurar seu projeto do Firebase para usar todas as opções. 301c9534f594f472.png
  3. Esta captura de tela mostra a saída no final do processo. Se você estiver familiarizado com o Firebase, notará que não foi necessário criar aplicativos de plataforma (por exemplo, um aplicativo Android) no console, e a CLI do FlutterFire fez isso por você. 12199a85ade30459.png

Quando isso estiver concluído, consulte o aplicativo Flutter em seu editor de texto. A CLI do FlutterFire gerou um novo arquivo chamado firebase_options.dart . Este arquivo contém uma classe chamada FirebaseOptions, que possui variáveis ​​estáticas que contêm a configuração do Firebase necessária para cada plataforma. Se você selecionou todas as plataformas ao executar flutterfire configure , verá valores estáticos chamados web , android , ios e 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.appspot.com',
   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.appspot.com',
 );

 static const FirebaseOptions ios = FirebaseOptions(
   apiKey: 'AIzaSyBqLWsqFjYAdGyihKTahMRDQMo0N6NVjAs',
   appId: '1:963656261848:ios:d9e01cfe8b675dfcb237ad',
   messagingSenderId: '963656261848',
   projectId: 'flutterfire-ui-codelab',
   storageBucket: 'flutterfire-ui-codelab.appspot.com',
   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.appspot.com',
   iosClientId: '963656261848-v7r3vq1v6haupv0l1mdrmsf56ktnua60.apps.googleusercontent.com',
   iosBundleId: 'com.example.complete',
 );
}

O Firebase usa a palavra aplicativo para se referir a uma compilação específica para uma plataforma específica em um projeto do Firebase. Por exemplo, o projeto Firebase chamado FlutterFire-ui-codelab possui vários aplicativos: um para Android, um para iOS, um para MacOS e um para Web.

O método DefaultFirebaseOptions.currentPlatform usa o enum TargetPlatform exposto pelo Flutter para detectar a plataforma em que seu aplicativo está sendo executado e, em seguida, retorna os valores de configuração do Firebase necessários para o aplicativo Firebase correto.

Adicionar pacotes do Firebase ao aplicativo Flutter

A etapa final de configuração é adicionar os pacotes Firebase relevantes ao seu projeto Flutter. O arquivo firebase_options.dart deve conter erros, pois depende de pacotes do Firebase que ainda não foram adicionados. No terminal, verifique se você está na raiz do projeto Flutter em flutter-codelabs/firebase-emulator-suite/start . Em seguida, execute os três comandos a seguir:

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

Estes são os únicos pacotes que você precisa neste momento.

Inicializar Firebase

Para utilizar os pacotes adicionados e o DefaultFirebaseOptions.currentPlatform, atualize o código na função main no arquivo main.dart .

principal.dart

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


 runApp(const MyApp());
}

Este código faz duas coisas.

  1. WidgetsFlutterBinding.ensureInitialized() diz ao Flutter para não começar a executar o código do widget do aplicativo até que a estrutura do Flutter seja completamente inicializada. O Firebase usa canais de plataforma nativos, que exigem que o framework esteja em execução.
  2. Firebase.initializeApp configura uma conexão entre seu aplicativo Flutter e seu projeto Firebase. O DefaultFirebaseOptions.currentPlatform é importado de nosso arquivo firebase_options.dart gerado. Esse valor estático detecta em qual plataforma você está executando e transmite as chaves correspondentes do Firebase.

4. Adicione a página inicial do Firebase UI Auth

O Firebase UI for Auth fornece widgets que representam telas inteiras do seu aplicativo. Essas telas lidam com diferentes fluxos de autenticação em todo o seu aplicativo, como Login, Registro, Esqueci a senha, Perfil do usuário e muito mais. Para começar, adicione uma landing page ao seu aplicativo que atue como uma proteção de autenticação para o aplicativo principal.

Material ou aplicativo Cupertino

A UI do FlutterFire requer que seu aplicativo seja empacotado em um MaterialApp ou CupertinoApp. Dependendo da sua escolha, a IU refletirá automaticamente as diferenças dos widgets Material ou Cupertino. Neste codelab, use MaterialApp , que já foi adicionado ao aplicativo em app.dart .

aplicativo.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(),
   );
 }
}

Verifique o estado de autenticação

Antes de poder exibir uma tela de login, você precisa determinar se o usuário está autenticado no momento. A maneira mais comum de verificar isso é ouvir authStateChanges do FirebaseAuth usando o plug-in Firebase Auth .

No exemplo de código acima, o MaterialApp está construindo um widget AuthGate em seu método de construção. (Este é um widget personalizado, não fornecido pela UI do FlutterFire.)

Esse widget precisa ser atualizado para incluir o fluxo authStateChanges .

A API authStateChanges retorna um Stream com o usuário atual (se ele estiver conectado) ou nulo se não estiver. Para assinar esse estado em nosso aplicativo, você pode usar o widget StreamBuilder do Flutter e passar o stream para ele.

StreamBuilder é um widget que se constrói com base no instantâneo mais recente de dados de um Stream que você passa. Ele reconstrói automaticamente quando o Stream emite um novo instantâneo.

Atualize o código em 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 está sendo passado FirebaseAuth.instance.authStateChanged , o stream mencionado acima, que retornará um objeto Firebase User se o usuário tiver se autenticado. (Caso contrário, retornará null .)
  • A seguir, o código usa snapshot.hasData para verificar se o valor do fluxo contém o objeto User .
  • Se não houver, retornará um widget SignInScreen . Atualmente, essa tela não fará nada. Isso será atualizado na próxima etapa.
  • Caso contrário, ele retorna um HomeScreen , que é a parte principal da aplicação que somente usuários autenticados podem acessar.

O SignInScreen é um widget que vem do pacote FlutterFire UI. Esse será o foco da próxima etapa deste codelab. Ao executar o aplicativo neste ponto, você verá uma tela de login em branco.

5. Tela de login

O widget SignInScreen , fornecido pela UI FlutterFire, adiciona a seguinte funcionalidade:

  • Permite que os usuários façam login
  • Se os usuários esquecerem a senha, poderão tocar em "Esqueceu a senha?" e será levado a um formulário para redefinir sua senha
  • Se um usuário ainda não estiver cadastrado, ele pode tocar em “Cadastre-se” e ser direcionado para outro formulário que permite a inscrição.

Novamente, isso requer apenas algumas linhas de código. Lembre-se do código no 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();
      },
    );
  }
}

O widget SignInScreen e seu argumento providers são o único código necessário para obter todas as funcionalidades mencionadas acima. Agora você deve ver uma tela de login com entradas de texto 'e-mail' e 'senha', bem como um botão 'Entrar'.

Embora funcional, falta estilo. O widget expõe parâmetros para personalizar a aparência da tela de login. Por exemplo, você pode querer adicionar o logotipo da sua empresa.

Personalize a tela de login

construtor de cabeçalho

Usando o argumento SignInScreen.headerBuilder , você pode adicionar quaisquer widgets que desejar acima do formulário de login. Atualize o arquivo auth_gate.dart com este código:

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();
     },
   );
 }
}

O argumento headerBuilder requer uma função do tipo HeaderBuilder, que é definida no pacote de UI do FlutterFire.

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

Por ser um retorno de chamada, ele expõe valores que você pode usar, como BuildContext e BoxConstraints e exige que você retorne um widget. Qualquer widget que você retornar será exibido na parte superior da tela. Neste exemplo, o novo código adiciona uma imagem ao topo da tela. Seu aplicativo agora deve ficar assim.

73d7548d91bbd2ab.png

Construtor de legendas

A tela de login expõe três parâmetros adicionais que permitem personalizar a tela: subtitleBuilder , footerBuilder e sideBuilder .

O subtitleBuilder é um pouco diferente porque os argumentos de retorno de chamada incluem uma ação, que é do tipo AuthAction . AuthAction é uma enumeração que você pode usar para detectar se a tela em que o usuário está é a tela de "login" ou a tela de "registro".

Atualize o código em auth_gate.dart para usar o 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();
     },
   );
 }
}

Recarregue o aplicativo e ele deverá ficar assim

O argumento footerBuilder é igual ao subtitleBuilder. Ele não expõe BoxConstraints ou shrinkOffset , pois se destina a texto e não a imagens. (Embora você possa adicionar qualquer widget que desejar.)

Adicione um rodapé à sua tela de login com este código.

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();
     },
   );
 }}

Construtor lateral

O argumento SignInScreen.sidebuilder aceita um retorno de chamada e, desta vez, os argumentos para esse retorno de chamada são BuildContext e double shrinkOffset . O widget retornado pelo sideBuilder será exibido à esquerda do formulário de login e apenas em telas amplas. Efetivamente, isso significa que o widget só será exibido em aplicativos de desktop e da web.

Internamente, a UI do FlutterFire usa um ponto de interrupção para determinar se o conteúdo do cabeçalho deve ser mostrado (em telas altas, como dispositivos móveis) ou o conteúdo lateral deve ser mostrado (em telas largas, desktop ou web). Especificamente, se uma tela tiver mais de 800 pixels de largura, o conteúdo do construtor lateral será mostrado e o conteúdo do cabeçalho não. Se a tela tiver menos de 800 pixels de largura, o oposto é verdadeiro.

Atualize o código em auth_gate.dart para adicionar 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();
     },
   );
 }
}

Seu aplicativo agora deve ficar assim quando você expande a largura da janela (se você estiver usando Flutter web ou MacOS).

8dc60b4e5d7dd2d0.png

Crie um usuário

Neste ponto, todo o código desta tela está concluído. Antes de fazer login, porém, você precisa criar um usuário. Você pode fazer isso na tela "Registrar" ou pode criar um usuário no console do Firebase.

Para usar o console:

  1. Vá para a tabela “Usuários” no console do Firebase.
  2. Clique aqui
  3. Selecione 'flutterfire-ui-codelab' (ou outro projeto se você usou um nome diferente). Você verá esta tabela:

f038fd9a58ed60d9.png

  1. Clique no botão "Adicionar usuário".

2d78390d4c5dbbfa.png

  1. Digite um endereço de e-mail e senha para o novo usuário. Pode ser um e-mail e uma senha falsos, conforme digitei na imagem abaixo. Isso funcionará, mas a funcionalidade “Esqueci a senha” não funcionará se você usar um endereço de e-mail falso.

62ba0feb33d54add.png

  1. Clique em "Adicionar usuário"

32b236b3ef94d4c7.png

Agora, você pode retornar ao seu aplicativo Flutter e fazer login de um usuário por meio da página de login. Seu aplicativo deve ficar assim:

dd43d260537f3b1a.png

6. Tela de perfil

A UI do FlutterFire também fornece um widget ProfileScreen , que, novamente, oferece muitas funcionalidades em algumas linhas de código.

Adicionar widget ProfileScreen

Navegue até o arquivo home.dart em seu editor de texto. Atualize-o com este código:

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(),
          ],
        ),
      ),
    );
  }
}

O novo código digno de nota é o retorno de chamada passado para o IconButton.isPressed method. Quando esse IconButton é pressionado, seu aplicativo cria uma nova rota anônima e navega até ela. Essa rota exibirá o widget ProfileScreen , que é retornado do retorno de chamada MaterialPageRoute.builder .

Recarregue seu aplicativo e pressione o ícone no canto superior direito (na barra de aplicativos) e uma página como esta será exibida:

36487fc4ab4f26a7.png

Esta é a UI padrão fornecida pela página UI do FlutterFire. Todos os botões e campos de texto estão conectados ao Firebase Auth e funcionam imediatamente. Por exemplo, você pode inserir um nome no campo de texto "Nome" e a UI do FlutterFire chamará o método FirebaseAuth.instance.currentUser?.updateDisplayName , que salvará esse nome no Firebase.

Saindo

No momento, se você pressionar o botão “Sair”, o aplicativo não será alterado. Ele desconectará você, mas você não será direcionado de volta ao widget AuthGate. Para implementar isso, use o parâmetro ProfileScreen.actions.

Primeiro, atualize o código em 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(),
          ],
        ),
      ),
    );
  }
}

Agora, ao criar uma instância de ProfileScreen , você também passa uma lista de ações para o argumento ProfileScreen.actions . Essas ações são do tipo FlutterFireUiAction . Existem muitas classes diferentes que são subtipos de FlutterFireUiAction e, em geral, você as usa para instruir seu aplicativo a reagir a diferentes alterações de estado de autenticação. O SignedOutAction chama uma função de retorno de chamada que você fornece quando o estado de autenticação do Firebase muda para currentUser sendo nulo.

Ao adicionar um retorno de chamada que chama Navigator.of(context).pop() quando SignedOutAction é acionado, o aplicativo navegará para a página anterior. Neste aplicativo de exemplo, há apenas uma rota permanente, que mostra a página de login se não houver um usuário conectado e a página inicial se houver um usuário. Como isso acontece quando o usuário sai, o aplicativo exibirá a página SignIn.

Personalize a página de perfil

Semelhante à página de login, a página de perfil é personalizável. Primeiro, nossa página atual não tem como voltar à página inicial quando o usuário está na página de perfil. Corrija isso fornecendo ao widget ProfileScreen um AppBar.

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(),
         ],
       ),
     ),
   );
 }
}

O argumento ProfileScreen.appBar aceita um widget AppBar do pacote Flutter Material, portanto, pode ser tratado como qualquer outro AppBar que você construiu e passou para um Scaffold . Neste exemplo, a funcionalidade padrão de adicionar automaticamente um botão “voltar” é mantida e a tela agora possui um título.

Adicionar crianças à tela de perfil

O widget ProfileScreen também possui um argumento opcional denominado filhos. Este argumento aceita uma lista de widgets, e esses widgets serão colocados verticalmente dentro de um widget Column que já foi usado internamente para construir o ProfileScreen. Este widget Coluna no método de construção ProfileScreen colocará os filhos que você passar acima do botão "Sair".

Atualize o código em home.dart para mostrar o logotipo da empresa aqui, semelhante à tela de login.

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(),
          ],
        ),
      ),
    );
  }
}

Recarregue seu aplicativo e você verá isto na tela:

ebe5792b765dbf87.png

7. Login de autenticação do Google multiplataforma

A UI do FlutterFire também fornece widgets e funcionalidades para autenticação com provedores terceirizados, como Google, Twitter, Facebook, Apple e Github.

Para integrar com a autenticação do Google, instale o plugin oficial firebase_ui_oauth_google e suas dependências, que irão lidar com o fluxo de autenticação nativa. No terminal, navegue até a raiz do seu projeto flutter e digite o seguinte comando:

flutter pub add google_sign_in
flutter pub add firebase_ui_oauth_google

Ativar provedor de login do Google

Em seguida, habilite o provedor Google no Firebase Console :

  1. Navegue até a tela Provedores de login de autenticação no console.
  2. Clique em "Adicionar novo provedor". 8286fb28be94bf30.png
  3. Selecione "Google". c4e28e6f4974be7f.png
  4. Alterne a chave rotulada como "Ativar" e pressione "Salvar". e74ff86990763826.png
  5. Caso apareça um modal com informações sobre o download dos arquivos de configuração, clique em “Concluído”.
  6. Confirme se o provedor de login do Google foi adicionado. 5329ce0543c90d95.png

Adicionar botão de login do Google

Com o login do Google ativado, adicione o widget necessário para exibir um botão estilizado de login do Google na página de login. Navegue até o arquivo auth_gate.dart e atualize o código para o seguinte:

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();
     },
   );
 }
}

O único código novo aqui é a adição de GoogleProvider(clientId: "YOUR_WEBCLIENT_ID") à configuração do widget SignInScreen.

Com isso adicionado, recarregue seu aplicativo e você verá um botão de login do Google.

aca71a46a011bfb5.png

Configurar botão de login

O botão não funciona sem configuração adicional. Se você estiver desenvolvendo com Flutter Web, esta é a única etapa que você precisa adicionar para que funcione. Outras plataformas requerem etapas adicionais, que serão discutidas em breve.

  1. Navegue até a página Provedores de autenticação no Firebase Console .
  2. Clique no provedor do Google. 9b3a325c5eca6e49.png
  3. Clique no painel de expansão "Configuração do Web SDK".
  4. Copie o valor de 'ID do cliente Web" 711a79f0d931c60f.png
  5. Retorne ao seu editor de texto e atualize a instância do GoogleProvider no arquivo auth_gate.dart passando esse ID para o parâmetro nomeado clientId .
GoogleProvider(
   clientId: "YOUR_WEBCLIENT_ID"
)

Depois que o ID do cliente web for inserido, recarregue seu aplicativo. Ao pressionar o botão "Fazer login com o Google", uma nova janela aparecerá (se você estiver usando a web) que o guiará pelo fluxo de login do Google. Inicialmente, fica assim:

14e73e3c9de704bb.png

Configurar iOS

Para que isso funcione no iOS, existe um processo de configuração adicional.

  1. Navegue até a tela Configurações do projeto no console do Firebase . Haverá um cartão que lista seus aplicativos do Firebase parecido com este: fefa674acbf213cc.png
  2. Clique no iOS. Observe que o nome do seu aplicativo será diferente do meu. Onde o meu diz "completo", o seu dirá "iniciar", se você usou o projeto flutter-codelabs/firebase-auth-flutterfire-ui/start para acompanhar este codelab.
  3. Clique no botão que diz “GoogleServices-Info.plist” para baixar o arquivo de configuração necessário. f89b3192871dfbe3.png
  4. Arraste e solte o arquivo baixado no diretório chamado . /ios/Runner em seu projeto Flutter.
  5. Abra o Xcode executando o seguinte comando de terminal na raiz do seu projeto:

abra ios/Runner.xcworkspace

  1. Clique com o botão direito no diretório Runner e selecione Adicionar arquivos ao "Runner". 858986063a4c5201.png
  2. Selecione GoogleService-Info.plist no gerenciador de arquivos.
  3. De volta ao seu editor de texto (que não é o Xcode), adicione os atributos CFBundleURLTypes abaixo ao arquivo [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 -->

Se o seu aplicativo Flutter já estiver em execução no iOS, você deverá desligá-lo completamente e executar o aplicativo novamente. Caso contrário, execute o aplicativo no iOS.

8. Parabéns!

Você concluiu o codelab Firebase Auth UI para Flutter. Você pode encontrar o código completo deste Codelab no diretório "complete" no github: Flutter Codelabs

O que cobrimos

  • Configurando um aplicativo Flutter para usar o Firebase
  • Configurando um projeto do Firebase no console do Firebase
  • CLI do FlutterFire
  • CLI do Firebase
  • Usando a autenticação Firebase
  • Usando a UI do FlutterFire para lidar facilmente com a autenticação do Firebase em seu aplicativo Flutter

Próximos passos

Saber mais

Sparky está aqui para comemorar com você!

2a0ad195769368b1.gif