Menambahkan alur autentikasi pengguna ke aplikasi Flutter menggunakan FirebaseUI

1. Sebelum memulai

Dalam codelab ini, Anda akan mempelajari cara menambahkan Firebase Authentication ke aplikasi Flutter menggunakan paket UI FlutterFire. Dengan paket ini, Anda akan menambahkan autentikasi email/sandi dan autentikasi Login dengan Google ke aplikasi Flutter. Anda juga akan mempelajari cara menyiapkan project Firebase, dan menggunakan FlutterFire CLI untuk melakukan inisialisasi Firebase di aplikasi Flutter.

Prasyarat

Codelab ini mengasumsikan bahwa Anda memiliki pengalaman menggunakan Flutter. Jika tidak, sebaiknya pelajari dasar-dasarnya terlebih dahulu. Link berikut akan membantu:

Anda juga seharusnya sudah memiliki pengalaman Firebase, tetapi tidak apa-apa jika belum pernah menambahkan Firebase ke project Flutter. Jika Anda tidak terbiasa dengan Firebase console, atau Anda benar-benar baru menggunakan Firebase, lihat link berikut terlebih dahulu:

Yang akan Anda buat

Codelab ini memandu Anda dalam membuat alur autentikasi untuk aplikasi Flutter, menggunakan Firebase untuk Autentikasi. Aplikasi akan memiliki layar login, layar 'Daftar', layar pemulihan sandi, dan layar profil pengguna.

6604fc9157f2c6ae.pngS eab9509a41074930.png da49189a5838e0bb.pngS b2ccfb3632b77878.png

Yang akan Anda pelajari

Codelab ini membahas:

  • Menambahkan Firebase ke aplikasi Flutter
  • Penyiapan Firebase Console
  • Menggunakan Firebase CLI untuk menambahkan Firebase ke aplikasi Anda
  • Menggunakan FlutterFire CLI untuk membuat konfigurasi Firebase di Dart
  • Menambahkan Firebase Authentication ke aplikasi Flutter Anda
  • Penyiapan Firebase Authentication di konsol
  • Menambahkan login dengan Email dan Sandi dengan paket firebase_ui_auth
  • Menambahkan pendaftaran pengguna dengan paket firebase_ui_auth
  • Menambahkan halaman 'Lupa sandi?'
  • Menambahkan Login dengan Google dengan firebase_ui_auth
  • Mengonfigurasi aplikasi Anda agar berfungsi dengan penyedia login banyak sekaligus.
  • Menambahkan layar profil pengguna ke aplikasi Anda dengan paket firebase_ui_auth

Codelab ini khusus membahas cara menambahkan sistem Autentikasi yang tangguh menggunakan paket firebase_ui_auth. Seperti yang akan Anda lihat, seluruh aplikasi ini, dengan semua fitur di atas, dapat diimplementasikan dengan sekitar 100 baris kode.

Yang Anda butuhkan

  • Pengetahuan praktis tentang Flutter dan SDK yang diinstal
  • Editor teks (JetBrains IDE, Android Studio, dan VS Code didukung oleh Flutter)
  • Browser Google Chrome, atau target pengembangan pilihan Anda lainnya untuk Flutter. (Beberapa perintah terminal dalam codelab ini akan mengasumsikan bahwa Anda menjalankan aplikasi di Chrome)

2. Membuat dan menyiapkan project Firebase

Tugas pertama yang harus Anda selesaikan adalah membuat project Firebase di konsol web Firebase.

Membuat project Firebase

  1. Login ke Firebase.
  2. Di Firebase console, klik Add Project (atau Create a project), lalu masukkan nama untuk project Firebase Anda (misalnya, "FlutterFire-UI-Codelab").

df42a5e3d9584b48.png

  1. Klik opsi pembuatan project. Setujui persyaratan Firebase jika diminta. Lewati penyiapan Google Analytics, karena Anda tidak akan menggunakan Analytics untuk aplikasi ini.

d1fcec48bf251eaa.png

Untuk mempelajari project Firebase lebih lanjut, lihat Memahami project Firebase.

Mengaktifkan login dengan email untuk Firebase Authentication

Aplikasi yang Anda build menggunakan Firebase Authentication untuk memungkinkan pengguna login ke aplikasi Anda. Aplikasi ini juga memungkinkan pengguna baru mendaftar dari aplikasi Flutter.

Firebase Authentication perlu diaktifkan menggunakan Firebase Console, dan memerlukan konfigurasi khusus setelah diaktifkan.

Untuk mengizinkan pengguna login ke aplikasi web, Anda harus menggunakan metode login Email/Sandi terlebih dahulu. Kemudian, Anda akan menambahkan metode Login dengan Google.

  1. Di Firebase console, luaskan menu Build di panel kiri.
  2. Klik Authentication, lalu klik tombol Get Started, lalu tab Sign-in method (atau klik di sini untuk langsung membuka tab Sign-in method).
  3. Klik Email/Sandi di daftar Penyedia login, setel tombol Aktifkan ke posisi aktif, lalu klik Simpan. 58e3e3e23c2f16a4.png

3. Menyiapkan aplikasi Flutter

Anda harus mendownload kode awal dan menginstal Firebase CLI sebelum kita memulai.

Mendapatkan kode awal

Clone repositori GitHub dari command line:

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

Atau, jika Anda telah menginstal alat CLI GitHub:

gh repo clone flutter/codelabs flutter-codelabs

Kode contoh harus di-clone ke direktori flutter-codelabs di mesin Anda, yang berisi kode untuk kumpulan codelab. Kode untuk codelab ini ada di sub-direktori flutter-codelabs/firebase-auth-flutterfire-ui.

Direktori flutter-codelabs/firebase-auth-flutterfire-ui berisi dua project Flutter. Salah satunya disebut complete dan yang lainnya disebut start. Direktori start berisi project yang tidak lengkap, dan di sinilah Anda akan menghabiskan sebagian besar waktu.

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

Jika Anda ingin melewati, atau melihat tampilan yang seharusnya setelah selesai, lihat direktori bernama complete untuk referensi silang.

Jika ingin mengikuti codelab, dan menambahkan kode sendiri, Anda harus memulai dengan aplikasi Flutter di flutter-codelabs/firebase-auth-flutterfire-ui/start, dan menambahkan kode ke project tersebut di seluruh codelab. Buka atau impor direktori tersebut ke IDE pilihan Anda.

Instal Firebase CLI

Firebase CLI menyediakan alat untuk mengelola project Firebase Anda. CLI diperlukan untuk FlutterFire CLI, yang akan Anda instal sebentar lagi.

Ada berbagai cara untuk menginstal CLI. Cara termudah, jika Anda menggunakan MacOS atau Linux, adalah dengan menjalankan perintah ini dari terminal:

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

Setelah menginstal CLI, Anda harus melakukan autentikasi dengan Firebase.

  1. Login ke Firebase menggunakan akun Google Anda dengan menjalankan perintah berikut:
firebase login
  1. Perintah ini menghubungkan komputer lokal Anda ke Firebase dan memberikan akses ke project Firebase Anda.
  1. Uji untuk memastikan bahwa CLI sudah diinstal dengan benar dan memiliki akses ke akun Anda dengan mencantumkan project Firebase Anda. Jalankan perintah berikut:
firebase projects:list
  1. Daftar yang ditampilkan harus sama dengan project Firebase yang tercantum di Firebase console. Anda akan melihat minimal flutterfire-ui-codelab.

Menginstal FlutterFire CLI

FlutterFire CLI adalah alat yang membantu mempermudah proses penginstalan Firebase di semua platform yang didukung di aplikasi Flutter Anda. Alat ini dibuat berdasarkan Firebase CLI.

Pertama, instal CLI:

dart pub global activate flutterfire_cli

Pastikan CLI telah diinstal. Jalankan perintah berikut dan pastikan CLI membuat output menu bantuan.

flutterfire -—help

Menambahkan project Firebase ke aplikasi Flutter Anda

Mengonfigurasi FlutterFire

Anda dapat menggunakan FlutterFire untuk membuat kode Dart yang diperlukan agar dapat menggunakan Firebase di aplikasi Flutter Anda.

flutterfire configure

Saat perintah ini dijalankan, Anda akan diminta untuk memilih project Firebase yang ingin digunakan, dan platform yang ingin disiapkan.

Screenshot berikut menunjukkan perintah yang harus Anda jawab.

  1. Pilih project yang ingin Anda gunakan. Dalam hal ini, gunakan flutterfire-ui-codelab 1359cdeb83204baa.pngS
  2. Pilih platform yang ingin Anda gunakan. Dalam codelab ini, ada langkah-langkah untuk mengonfigurasi Firebase Authentication untuk Flutter untuk web, iOS, dan Android, tetapi Anda dapat menyiapkan project Firebase untuk menggunakan semua opsi. 301c9534f594f472.png
  3. Screenshot ini menampilkan output di akhir proses. Jika sudah terbiasa dengan Firebase, Anda akan melihat bahwa Anda tidak perlu membuat aplikasi platform (misalnya, aplikasi Android) di konsol, dan FlutterFire CLI melakukannya untuk Anda. 12199a85ade30459.pngS

Setelah selesai, lihat aplikasi Flutter di editor teks Anda. FlutterFire CLI telah membuat file baru bernama firebase_options.dart. File ini berisi class bernama FirebaseOptions, yang memiliki variabel statis yang menyimpan konfigurasi Firebase yang diperlukan untuk setiap platform. Jika memilih semua platform saat menjalankan flutterfire configure, Anda akan melihat nilai statis bernama web, android, ios, dan 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 menggunakan kata "aplikasi" untuk merujuk ke build spesifik untuk platform tertentu dalam project Firebase. Misalnya, project Firebase bernama FlutterFire-ui-codelab memiliki beberapa aplikasi: satu untuk Android, satu untuk iOS, satu untuk MacOS, dan satu untuk Web.

Metode DefaultFirebaseOptions.currentPlatform menggunakan enum TargetPlatform yang diekspos oleh Flutter untuk mendeteksi platform tempat aplikasi Anda berjalan, lalu menampilkan nilai konfigurasi Firebase yang diperlukan untuk aplikasi Firebase yang benar.

Menambahkan paket Firebase ke aplikasi Flutter

Langkah penyiapan terakhir adalah menambahkan paket Firebase yang relevan ke project Flutter Anda. File firebase_options.dart akan mengalami error karena bergantung pada paket Firebase yang belum ditambahkan. Di terminal, pastikan Anda berada di root project Flutter di flutter-codelabs/firebase-emulator-suite/start. Kemudian, jalankan tiga perintah berikut:

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

Ini adalah satu-satunya paket yang Anda perlukan saat ini.

Melakukan inisialisasi Firebase

Untuk menggunakan paket yang ditambahkan, dan DefaultFirebaseOptions.currentPlatform, memperbarui kode dalam fungsi main di file main.dart.

main.dart

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


 runApp(const MyApp());
}

Kode ini melakukan dua hal.

  1. WidgetsFlutterBinding.ensureInitialized() memberi tahu Flutter agar tidak mulai menjalankan kode widget aplikasi hingga framework Flutter selesai di-booting. Firebase menggunakan saluran platform native, yang mengharuskan framework berjalan.
  2. Firebase.initializeApp menyiapkan koneksi antara aplikasi Flutter dan project Firebase Anda. DefaultFirebaseOptions.currentPlatform diimpor dari file firebase_options.dart yang dihasilkan. Nilai statis ini mendeteksi platform tempat Anda menjalankan aplikasi, dan meneruskan kunci Firebase yang sesuai.

4. Menambahkan halaman Auth UI Firebase awal

UI Firebase untuk Auth menyediakan widget yang mewakili seluruh layar di aplikasi Anda. Layar ini menangani alur autentikasi yang berbeda di seluruh aplikasi Anda, seperti Login, Pendaftaran, Lupa Sandi, Profil Pengguna, dan lainnya. Untuk memulai, tambahkan halaman landing ke aplikasi Anda yang berfungsi sebagai pengaman autentikasi ke aplikasi utama.

Material atau Aplikasi Cupertino

UI FlutterFire mengharuskan aplikasi Anda digabungkan dalam MaterialApp atau CupertinoApp. Bergantung pada pilihan Anda, UI akan otomatis mencerminkan perbedaan widget Material atau Cupertino. Untuk codelab ini, gunakan MaterialApp, yang sudah ditambahkan ke aplikasi di 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(),
   );
 }
}

Memeriksa status autentikasi

Sebelum dapat menampilkan layar login, Anda perlu menentukan apakah pengguna saat ini diautentikasi. Cara paling umum untuk memeriksanya adalah dengan memproses authStateChanges FirebaseAuth menggunakan plugin Firebase Auth.

Dalam contoh kode di atas, MaterialApp mem-build widget AuthGate dalam metode build-nya. (Ini adalah widget kustom, yang tidak disediakan oleh UI FlutterFire.)

Widget tersebut perlu diupdate untuk menyertakan streaming authStateChanges.

authStateChanges API menampilkan Stream dengan pengguna saat ini (jika pengguna login), atau null jika pengguna tidak login. Untuk berlangganan status ini di aplikasi kami, Anda dapat menggunakan widget StreamBuilder Flutter dan meneruskan streaming ke widget tersebut.

StreamBuilder adalah widget yang membuat dirinya sendiri berdasarkan snapshot data terbaru dari Aliran Data yang Anda teruskan. Model ini akan otomatis dibuat ulang saat Streaming memunculkan snapshot baru.

Perbarui kode di 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 diteruskan FirebaseAuth.instance.authStateChanged, streaming yang disebutkan di atas, yang akan menampilkan objek User Firebase jika pengguna telah melakukan autentikasi. (Jika tidak, null akan ditampilkan.)
  • Selanjutnya, kode tersebut menggunakan snapshot.hasData untuk memeriksa apakah nilai dari aliran data berisi objek User.
  • Jika tidak ada, widget SignInScreen akan ditampilkan. Saat ini, layar tersebut tidak akan melakukan apa pun. Hal ini akan diperbarui di langkah berikutnya.
  • Jika tidak, HomeScreen akan ditampilkan, yang merupakan bagian utama aplikasi yang hanya dapat diakses oleh pengguna terautentikasi.

SignInScreen adalah widget yang berasal dari paket UI FlutterFire. Hal ini akan menjadi fokus dari langkah berikutnya di codelab ini. Saat menjalankan aplikasi pada tahap ini, Anda akan melihat layar login kosong.

5. Layar Login

Widget SignInScreen, yang disediakan oleh UI FlutterFire, menambahkan fungsi berikut:

  • Mengizinkan pengguna untuk login
  • Jika lupa sandi, pengguna dapat mengetuk "Lupa sandi?" dan diarahkan ke formulir untuk mereset sandi
  • Jika pengguna belum terdaftar, dia dapat mengetuk "Daftar", dan diarahkan ke formulir lain yang memungkinkannya untuk mendaftar.

Sekali lagi, ini hanya memerlukan beberapa baris kode. Ingat kembali kode di 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();
      },
    );
  }
}

Widget SignInScreen, dan argumen providers-nya, adalah satu-satunya kode yang diperlukan untuk mendapatkan semua fungsi yang disebutkan di atas. Sekarang Anda akan melihat layar login yang memiliki input teks 'email' dan 'sandi', serta tombol 'Login'.

Meskipun fungsional, perangkat ini tidak memiliki gaya. Widget ini mengekspos parameter untuk menyesuaikan tampilan layar login. Misalnya, Anda mungkin ingin menambahkan logo perusahaan.

Menyesuaikan Layar login

headerBuilder

Dengan menggunakan argumen SignInScreen.headerBuilder, Anda dapat menambahkan widget apa pun yang diinginkan di atas formulir login. Widget ini hanya ditampilkan pada layar sempit, seperti perangkat seluler. Di layar lebar, Anda dapat menggunakan SignInScreen.sideBuilder, yang akan dibahas nanti dalam codelab ini.

Perbarui file auth_gate.dart dengan kode ini:

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

Argumen headerBuilder memerlukan fungsi dari jenis HeaderBuilder, yang ditentukan dalam paket UI FlutterFire.

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

Karena merupakan callback, metode ini mengekspos nilai yang dapat Anda gunakan, seperti BuildContext dan BoxConstraints, dan mengharuskan Anda menampilkan widget. Widget apa pun yang Anda tampilkan akan ditampilkan di bagian atas layar. Dalam contoh ini, kode baru menambahkan gambar ke bagian atas layar. Aplikasi Anda sekarang akan terlihat seperti ini.

73d7548d91bbd2ab.png

Pembuat Subtitel

Layar login menampilkan tiga parameter tambahan yang memungkinkan Anda menyesuaikan layar: subtitleBuilder, footerBuilder, dan sideBuilder.

subtitleBuilder sedikit berbeda karena argumen callback menyertakan tindakan, yang berjenis AuthAction. AuthAction adalah enum yang dapat Anda gunakan untuk mendeteksi apakah layar yang digunakan pengguna adalah layar "login" atau layar "daftar".

Perbarui kode di auth_gate.dart untuk menggunakan 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();
     },
   );
 }
}

Muat ulang aplikasi, dan seharusnya terlihat seperti ini

Argumen footerBuilder sama dengan subtitleBuilder. Mode ini tidak mengekspos BoxConstraints atau shrinkOffset, karena ditujukan untuk teks, bukan gambar. (Meskipun Anda dapat menambahkan widget apa pun yang Anda inginkan.)

Tambahkan footer ke layar login Anda dengan kode ini.

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

Builder Samping

Argumen SignInScreen.sidebuilder menerima callback, dan kali ini argumen untuk callback tersebut adalah BuildContext dan double shrinkOffset. Widget yang ditampilkan sideBuilder akan ditampilkan di sebelah kiri formulir login, dan hanya di layar lebar. Artinya, widget hanya akan ditampilkan di aplikasi desktop dan web.

Secara internal, UI FlutterFire menggunakan titik henti sementara untuk menentukan apakah konten header harus ditampilkan (di layar yang tinggi, seperti perangkat seluler) atau konten samping harus ditampilkan (di layar lebar, desktop, atau web). Secara khusus, jika lebar layar lebih dari 800 piksel, konten builder samping akan ditampilkan, dan konten header tidak akan ditampilkan. Jika lebar layar kurang dari 800 piksel, hal sebaliknya akan berlaku.

Perbarui kode di auth_gate.dart untuk menambahkan widget 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();
     },
   );
 }
}

Aplikasi Anda sekarang akan terlihat seperti ini saat memperluas lebar jendela (jika Anda menggunakan Flutter web atau MacOS).

8dc60b4e5d7dd2d0.pngS

Membuat pengguna

Pada tahap ini, semua kode untuk layar ini sudah selesai. Namun, sebelum dapat login, Anda harus membuat Pengguna. Anda dapat melakukannya dengan layar "Daftar", atau Anda dapat membuat pengguna di Firebase console.

Untuk menggunakan konsol:

  1. Buka tabel "Pengguna" di Firebase console.
  2. Klik di sini
  3. Pilih 'flutterfire-ui-codelab' (atau project lain jika Anda menggunakan nama yang berbeda). Anda akan melihat tabel ini:

f038fd9a58ed60d9.png

  1. Klik tombol "Tambahkan pengguna".

2d78390d4c5dbbfa.pngS

  1. Masukkan alamat email dan sandi untuk pengguna baru. Ini bisa saja email dan kata sandi palsu, seperti yang saya masukkan pada gambar di bawah. Hal ini akan berfungsi, tetapi fungsi "Lupa sandi" tidak akan berfungsi jika Anda menggunakan alamat email palsu.

62ba0feb33d54add.png

  1. Klik "Tambahkan pengguna"

32b236b3ef94d4c7.pngS

Sekarang, Anda dapat kembali ke aplikasi Flutter, dan login pengguna melalui halaman login. Aplikasi Anda akan terlihat seperti ini:

dd43d260537f3b1a.pngS

6. Layar Profil

UI FlutterFire juga menyediakan widget ProfileScreen, yang sekali lagi memberi Anda banyak fungsi dalam beberapa baris kode.

Menambahkan widget ProfileScreen

Buka file home.dart di editor teks Anda. Perbarui dengan kode ini:

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

Kode catatan baru adalah callback yang diteruskan ke IconButton.isPressed method. Saat IconButton tersebut ditekan, aplikasi Anda akan membuat rute anonim baru dan membukanya. Rute tersebut akan menampilkan widget ProfileScreen, yang ditampilkan dari callback MaterialPageRoute.builder.

Muat ulang aplikasi, lalu tekan ikon di kanan atas (di panel aplikasi), dan halaman seperti ini akan ditampilkan:

36487fc4ab4f26a7.pngS

Ini adalah UI standar yang disediakan oleh halaman UI FlutterFire. Semua tombol dan kolom teks terhubung ke Firebase Auth, dan berfungsi secara otomatis. Misalnya, Anda dapat memasukkan nama ke kolom teks "Nama", dan UI FlutterFire akan memanggil metode FirebaseAuth.instance.currentUser?.updateDisplayName, yang akan menyimpan nama tersebut di Firebase.

Logout

Saat ini, jika Anda menekan tombol "Sign out", aplikasi tidak akan berubah. Anda akan logout, tetapi Anda tidak akan diarahkan kembali ke widget AuthGate. Untuk menerapkannya, gunakan parameter ProfileScreen.actions.

Pertama, perbarui kode di 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(),
          ],
        ),
      ),
    );
  }
}

Sekarang, saat membuat instance ProfileScreen, Anda juga meneruskan daftar tindakan ke argumen ProfileScreen.actions. Tindakan ini adalah jenis FlutterFireUiAction. Ada banyak class berbeda yang merupakan subjenis FlutterFireUiAction, dan secara umum Anda menggunakannya untuk memberi tahu aplikasi Anda agar bereaksi terhadap perubahan status autentikasi yang berbeda. SignedOutAction memanggil fungsi callback yang Anda berikan saat status autentikasi Firebase berubah menjadi currentUser null.

Dengan menambahkan callback yang memanggil Navigator.of(context).pop() saat SignedOutAction dipicu, aplikasi akan membuka halaman sebelumnya. Di aplikasi contoh ini, hanya ada satu rute permanen, yang menampilkan halaman login jika tidak ada pengguna yang login, dan halaman beranda jika ada pengguna. Karena hal ini terjadi saat pengguna logout, aplikasi akan menampilkan halaman Login.

Sesuaikan Halaman Profil

Serupa dengan halaman Login, halaman profil dapat disesuaikan. Pertama, halaman saat ini tidak dapat digunakan untuk kembali ke halaman beranda setelah pengguna berada di halaman profil. Perbaiki dengan memberi widget ProfileScreen 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(),
         ],
       ),
     ),
   );
 }
}

Argumen ProfileScreen.appBar menerima widget AppBar dari paket Material Flutter sehingga dapat diperlakukan seperti AppBar lain yang telah Anda bangun dan teruskan ke Scaffold. Dalam contoh ini, fungsi default untuk menambahkan tombol &quot;kembali&quot; secara otomatis dipertahankan, dan layar kini memiliki judul.

Tambahkan Anak ke Layar Profil

Widget ProfileScreen juga memiliki argumen opsional yang bernama turunan. Argumen ini menerima daftar widget, dan widget tersebut akan ditempatkan secara vertikal di dalam widget Column yang sudah digunakan secara internal untuk mem-build ProfileScreen. Widget Column ini dalam metode build ProfileScreen akan menempatkan turunan yang Anda teruskan di atas tombol &quot;Logout&quot;.

Perbarui kode di home.dart untuk menampilkan logo perusahaan di sini, mirip dengan layar 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(),
          ],
        ),
      ),
    );
  }
}

Muat ulang aplikasi, dan Anda akan melihat ini di layar:

ebe5792b765dbf87.pngS

7. Login Google Auth Multiplatform

UI FlutterFire juga menyediakan widget dan fungsi untuk mengautentikasi dengan penyedia pihak ketiga, seperti Google, Twitter, Facebook, Apple, dan GitHub.

Untuk berintegrasi dengan autentikasi Google, instal plugin firebase_ui_oauth_google resmi beserta dependensinya, yang akan menangani alur autentikasi native. Di terminal, buka root project flutter Anda dan masukkan perintah berikut:

flutter pub add google_sign_in
flutter pub add firebase_ui_oauth_google

Aktifkan Penyedia Login dengan Google

Selanjutnya, aktifkan penyedia Google di Firebase Console:

  1. Buka layar Penyedia login autentikasi di konsol.
  2. Klik "Tambahkan penyedia baru". 8286fb28be94bf30.pngS
  3. Pilih "Google". c4e28e6f4974be7f.pngS
  4. Alihkan tombol berlabel "Aktifkan", lalu tekan "Simpan". e74ff86990763826.pngS
  5. Jika modal muncul dengan informasi tentang mendownload file konfigurasi, klik "Selesai".
  6. Pastikan penyedia login Google telah ditambahkan. 5329ce0543c90d95.pngS

Tambahkan tombol login dengan Google

Setelah login dengan Google diaktifkan, tambahkan widget yang diperlukan untuk menampilkan tombol login dengan Google bergaya ke halaman login. Buka file auth_gate.dart dan perbarui kode menjadi berikut:

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

Satu-satunya kode baru di sini adalah penambahan GoogleProvider(clientId: "YOUR_WEBCLIENT_ID") ke konfigurasi widget SignInScreen.

Setelah menambahkannya, muat ulang aplikasi, dan Anda akan melihat tombol login dengan Google.

aca71a46a011bfb5.pngS

Tombol Konfigurasi login

Tombol tidak berfungsi tanpa konfigurasi tambahan. Jika Anda mengembangkan aplikasi dengan Web Flutter, ini adalah satu-satunya langkah yang harus Anda tambahkan agar berfungsi. Platform lain memerlukan langkah tambahan, yang akan dibahas sebentar lagi.

  1. Buka halaman Penyedia Autentikasi di Firebase Console.
  2. Klik penyedia Google. 9b3a325c5eca6e49.pngS
  3. Klik panel perluasan "Konfigurasi Web SDK".
  4. Salin nilai dari ‘Client ID web" 711a79f0d931c60f.png
  5. Kembali ke editor teks Anda, dan update instance GoogleProvider dalam file auth_gate.dart dengan meneruskan ID ini ke parameter bernama clientId.
GoogleProvider(
   clientId: "YOUR_WEBCLIENT_ID"
)

Setelah client ID web dimasukkan, muat ulang aplikasi Anda. Saat Anda menekan tombol "Login dengan Google", jendela baru akan muncul (jika Anda menggunakan web) yang memandu Anda melalui alur login Google. Awalnya, tampilannya seperti ini:

14e73e3c9de704bb.png

Mengonfigurasi iOS

Agar hal ini berfungsi di iOS, ada proses konfigurasi tambahan.

  1. Buka layar Project Settings di Firebase console. Akan ada kartu yang mencantumkan aplikasi Firebase Anda yang terlihat seperti ini: fefa674acbf213cc.png
  2. Klik iOS. Perhatikan bahwa nama aplikasi Anda akan berbeda dengan nama saya. Jika saya menggunakan project flutter-codelabs/firebase-auth-flutterfire-ui/start untuk mengikuti codelab ini, project Anda akan menampilkan "start", bukan "complete".
  3. Klik tombol bertuliskan "GoogleServices-Info.plist" untuk mendownload file konfigurasi yang diperlukan. f89b3192871dfbe3.pngS
  4. Tarik lalu lepas file yang didownload ke direktori yang disebut ./ios/Runner di project Flutter Anda.
  5. Buka Xcode dengan menjalankan perintah terminal berikut dari root project Anda: open ios/Runner.xcworkspace
  6. Klik kanan direktori Runner, lalu pilih Add Files to "Runner". 858986063a4c5201.png
  7. Pilih GoogleService-Info.plist dari pengelola file.
  8. Kembali ke editor teks Anda (yang bukan Xcode), tambahkan atribut CFBundleURLTypes di bawah ke file [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. Anda harus mengganti GoogleProvider.clientId yang ditambahkan di penyiapan web dengan Client-ID yang terkait dengan client ID iOS Firebase. Pertama, Anda dapat menemukan ID ini dalam file firebase_options.dart, sebagai bagian dari konstanta iOS. Salin nilai yang diteruskan ke 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. Tempelkan nilai tersebut ke argumen GoogleProvider.clientId di 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();
     },
   );
 }
}

Jika aplikasi Flutter Anda sudah berjalan di iOS, Anda harus mematikan sepenuhnya lalu menjalankan kembali aplikasi tersebut. Jika tidak, jalankan aplikasi di iOS.

8. Selamat!

Anda telah menyelesaikan codelab UI Firebase Auth untuk Flutter. Anda dapat menemukan kode lengkap untuk Codelab ini di direktori "complete" di GitHub: Codelab Flutter

Yang telah kita bahas

  • Menyiapkan aplikasi Flutter untuk menggunakan Firebase
  • Menyiapkan project Firebase di Firebase console
  • FlutterFire CLI
  • Firebase CLI
  • Menggunakan Firebase Authentication
  • Menggunakan UI FlutterFire untuk menangani autentikasi Firebase di aplikasi Flutter dengan mudah

Langkah Berikutnya

Pelajari lebih lanjut

Sparky hadir untuk merayakannya bersama Anda!

2a0ad195769368b1.gif