FirebaseUI を使用してユーザー認証フローを Flutter アプリに追加する

1. 始める前に

このコードラボでは、FlutterFire UI パッケージを使用して Firebase Authentication を Flutter アプリに追加する方法を学習します。このパッケージを使用すると、メール/パスワード認証と Google サインイン認証の両方を Flutter アプリに追加します。また、Firebase プロジェクトをセットアップする方法、および FlutterFire CLI を使用して Flutter アプリで Firebase を初期化する方法も学習します。

前提条件

このコードラボは、ある程度の Flutter 経験があることを前提としています。そうでない場合は、まず基本を学習するとよいでしょう。次のリンクが役に立ちます。

Firebase の経験も必要ですが、Flutter プロジェクトに Firebase を追加したことがなくても大丈夫です。 Firebase コンソールに慣れていない場合、または Firebase をまったく初めて使用する場合は、まず次のリンクを参照してください。

作成するもの

このコードラボでは、認証に Firebase を使用して、Flutter アプリの認証フローを構築する方法を説明します。アプリケーションには、ログイン画面、「登録」画面、パスワード回復画面、およびユーザー プロファイル画面があります。

6604fc9157f2c6ae.pngeab9509a41074930.pngda49189a5838e0bb.pngb2ccfb3632b77878.png

学べること

このコードラボでは以下をカバーします。

  • Flutter アプリに Firebase を追加する
  • Firebase コンソールのセットアップ
  • Firebase CLI を使用して Firebase をアプリケーションに追加する
  • FlutterFire CLI を使用して Dart で Firebase 構成を生成する
  • Flutter アプリに Firebase Authentication を追加する
  • コンソールでの Firebase Authentication の設定
  • firebase_ui_authパッケージを使用した電子メールとパスワードのサインインの追加
  • firebase_ui_authパッケージを使用したユーザー登録の追加
  • 「パスワードをお忘れですか?」の追加ページ
  • firebase_ui_authを使用した Google サインインの追加
  • 複数のサインイン プロバイダーで動作するようにアプリを構成します。
  • firebase_ui_authパッケージを使用してアプリケーションにユーザー プロフィール画面を追加する

このコードラボは、特にfirebase_ui_authパッケージを使用した堅牢な認証システムの追加に関係しています。ご覧のとおり、上記の機能をすべて備えたこのアプリ全体は、約 100 行のコードで実装できます。

必要なもの

  • Flutterとインストールされた SDK に関する実用的な知識
  • テキスト エディター (JetBrains IDE、Android Studio、VS Code は Flutter でサポートされています)
  • Google Chrome ブラウザ、または Flutter のその他の優先開発ターゲット。 (このコードラボの一部のターミナル コマンドは、Chrome でアプリを実行していることを前提としています)

2. Firebase プロジェクトを作成して設定する

完了する必要がある最初のタスクは、Firebase の Web コンソールで Firebase プロジェクトを作成することです。

Firebaseプロジェクトを作成する

  1. Firebaseにサインインします。
  2. Firebase コンソールで、 [プロジェクトの追加] (または[プロジェクトの作成]) をクリックし、Firebase プロジェクトの名前を入力します (例: 「 FlutterFire-UI-Codelab 」)。

df42a5e3d9584b48.png

  1. プロジェクト作成オプションをクリックして進みます。プロンプトが表示されたら、Firebase の利用規約に同意します。このアプリでは Analytics を使用しないため、Google Analytics の設定はスキップします。

d1fcec48bf251eaa.png

Firebase プロジェクトの詳細については、 「Firebase プロジェクトを理解する」を参照してください。

構築しているアプリはFirebase Authenticationを使用して、ユーザーがアプリにサインインできるようにします。また、Flutter アプリケーションから新規ユーザーを登録することもできます。

Firebase Authentication はFirebase コンソールを使用して有効にする必要があり、有効にした後は特別な構成が必要です。

Firebase Authentication のメール サインインを有効にする

ユーザーが Web アプリにサインインできるようにするには、まず電子メール/パスワードによるサインイン方法を使用します。後で、 Google サインイン方法を追加します。

  1. Firebase コンソールで、左側のパネルの[Build]メニューを展開します。
  2. [認証]をクリックし、 [開始する]ボタンをクリックして、 [サインイン方法]タブをクリックします (または、ここをクリックして[サインイン方法]タブに直接移動します)。
  3. [サインイン プロバイダー]リストで[電子メール/パスワード]をクリックし、 [有効]スイッチをオンの位置に設定して、 [保存]をクリックします。 58e3e3e23c2f16a4.png

3. Flutterアプリをセットアップする

始める前に、スターター コードをダウンロードし、Firebase CLI をインストールする必要があります。

スターターコードを取得する

コマンドラインからGitHub リポジトリのクローンを作成します。

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

あるいは、 GitHub のCLI ツールがインストールされている場合は、次のようにします。

gh repo clone flutter/codelabs flutter-codelabs

サンプル コードは、コードラボのコレクションのコードが含まれるマシン上のflutter-codelabsディレクトリに複製する必要があります。このコードラボのコードは、サブディレクトリflutter-codelabs/firebase-auth-flutterfire-uiにあります。

flutter-codelabs/firebase-auth-flutterfire-uiディレクトリには 2 つの Flutter プロジェクトが含まれています。 1 つはcompleteと呼ばれ、もう 1 つはstartと呼ばれます。 startディレクトリには不完全なプロジェクトが含まれており、最も多くの時間を費やすことになります。

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

先に進みたい場合、または完了時にどのようになるかを確認したい場合は、相互参照のために complete という名前のディレクトリを調べてください。

コードラボに従って、自分でコードを追加したい場合は、 flutter-codelabs/firebase-auth-flutterfire-ui/startにある Flutter アプリから始めて、コードラボ全体でそのプロジェクトにコードを追加する必要があります。そのディレクトリを開くか、好みの IDE にインポートします。

Firebase CLIをインストールする

Firebase CLI は、Firebase プロジェクトを管理するためのツールを提供します。 FlutterFire CLI には CLI が必要です。これについては後でインストールします。

CLI をインストールするにはさまざまな方法があります。 MacOS または Linux を使用している場合、最も簡単な方法は、ターミナルから次のコマンドを実行することです。

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

CLI をインストールした後、Firebase で認証する必要があります。

  1. 次のコマンドを実行して、Google アカウントを使用して Firebase にログインします。
firebase login
  1. このコマンドは、ローカル マシンを Firebase に接続し、Firebase プロジェクトへのアクセスを許可します。
  1. Firebase プロジェクトを一覧表示して、CLI が適切にインストールされており、アカウントにアクセスできることをテストします。次のコマンドを実行します。
firebase projects:list
  1. 表示されるリストは、 Firebase コンソールにリストされる Firebase プロジェクトと同じである必要があります。少なくともflutterfire-ui-codelab.

FlutterFire CLI をインストールする

FlutterFire CLI は、Flutter アプリでサポートされているすべてのプラットフォームで Firebase のインストール プロセスを容易にするツールです。これは Firebase CLI の上に構築されています。

まず、CLI をインストールします。

dart pub global activate flutterfire_cli

CLI がインストールされていることを確認してください。次のコマンドを実行し、CLI がヘルプ メニューを出力することを確認します。

flutterfire -—help

Firebase プロジェクトを Flutter アプリに追加します

FlutterFireを構成する

FlutterFire を使用して、Flutter アプリで Firebase を使用するために必要な Dart コードを生成できます。

flutterfire configure

このコマンドを実行すると、使用する Firebase プロジェクトとセットアップするプラットフォームを選択するよう求められます。

次のスクリーンショットは、回答する必要があるプロンプトを示しています。

  1. 使用するプロジェクトを選択します。この場合、 flutterfire-ui-codelabを使用します。 1359cdeb83204baa.png
  2. 使用するプラットフォームを選択します。このコードラボには、ウェブ、iOS、Android 用の Flutter の Firebase Authentication を構成する手順がありますが、すべてのオプションを使用するように Firebase プロジェクトを設定することもできます。 301c9534f594f472.png
  3. このスクリーンショットは、プロセスの終了時の出力を示しています。 Firebase に精通している場合は、コンソールでプラットフォーム アプリケーション (Android アプリケーションなど) を作成する必要がなく、FlutterFire CLI が自動的に作成してくれることに気づくでしょう。 12199a85ade30459.png

これが完了したら、テキスト エディターで Flutter アプリを確認します。 FlutterFire CLI は、 firebase_options.dartという新しいファイルを生成しました。このファイルには FirebaseOptions というクラスが含まれており、このクラスには各プラットフォームに必要な Firebase 設定を保持する静的変数があります。 flutterfire configureの実行時にすべてのプラットフォームを選択した場合は、 webandroidios 、および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',
 );
}

Firebase では、Firebase プロジェクト内の特定のプラットフォーム用の特定のビルドを指すためにアプリケーションという言葉を使用します。たとえば、FlutterFire-ui-codelab という Firebase プロジェクトには、Android 用、iOS 用、MacOS 用、Web 用の複数のアプリケーションがあります。

メソッドDefaultFirebaseOptions.currentPlatform 、Flutter によって公開されたTargetPlatform列挙型を使用してアプリが実行されているプラ​​ットフォームを検出し、正しい Firebase アプリケーションに必要な Firebase 構成値を返します。

Firebase パッケージを Flutter アプリに追加する

最後のセットアップ手順は、関連する Firebase パッケージを Flutter プロジェクトに追加することです。 firebase_options.dartファイルはまだ追加されていない Firebase パッケージに依存しているため、エラーが発生するはずです。ターミナルで、 Flutter プロジェクトのルートflutter-codelabs/firebase-emulator-suite/startにいることを確認します。次に、次の 3 つのコマンドを実行します。

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

現時点で必要なパッケージはこれらだけです。

Firebaseを初期化する

追加されたパッケージとDefaultFirebaseOptions.currentPlatform, main.dartファイルのmain関数のコードを更新します。

メインダーツ

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


 runApp(const MyApp());
}

このコードは 2 つのことを行います。

  1. WidgetsFlutterBinding.ensureInitialized()は、Flutter フレームワークが完全に起動するまでアプリケーション ウィジェット コードの実行を開始しないように Flutter に指示します。 Firebase はネイティブ プラットフォーム チャネルを使用するため、フレームワークが実行されている必要があります。
  2. Firebase.initializeApp Flutter アプリと Firebase プロジェクト間の接続を設定します。 DefaultFirebaseOptions.currentPlatformは、生成されたfirebase_options.dartファイルからインポートされます。この静的な値は、実行しているプラ​​ットフォームを検出し、対応する Firebase キーを渡します。

4. 最初の Firebase UI 認証ページを追加します

Firebase UI for Auth は、アプリケーションの画面全体を表すウィジェットを提供します。これらの画面は、サインイン、登録、パスワードを忘れた場合、ユーザー プロファイルなど、アプリケーション全体のさまざまな認証フローを処理します。まず、メイン アプリケーションの認証ガードとして機能するランディング ページをアプリに追加します。

マテリアルまたはクパチーノ アプリ

FlutterFire UI では、アプリケーションが MaterialApp または CupertinoApp でラップされている必要があります。選択に応じて、UI はマテリアル ウィジェットまたはクパチーノ ウィジェットの違いを自動的に反映します。このコードラボでは、 app.dartのアプリにすでに追加されているMaterialAppを使用します。

アプリダーツ

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

認証状態を確認する

サインイン画面を表示する前に、ユーザーが現在認証されているかどうかを確認する必要があります。これを確認する最も一般的な方法は、 Firebase Auth プラグインを使用して FirebaseAuth の authStateChanges をリッスンすることです。

上記のコード サンプルでは、 MaterialAppがその build メソッドでAuthGateウィジェットを構築しています。 (これはカスタム ウィジェットであり、FlutterFire UI によって提供されるものではありません。)

このウィジェットを更新してauthStateChangesストリームを含める必要があります。

authStateChanges API は、現在のユーザー (サインインしている場合) を含むStreamを返し、サインインしていない場合は null を返します。アプリケーションでこの状態をサブスクライブするには、Flutter のStreamBuilderウィジェットを使用して、それにストリームを渡すことができます。

StreamBuilder 、渡されたストリームからのデータの最新スナップショットに基づいて自身を構築するウィジェットです。ストリームが新しいスナップショットを発行すると、自動的に再構築されます。

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は、前述のストリームであるFirebaseAuth.instance.authStateChangedが渡されます。これは、ユーザーが認証されている場合に Firebase Userオブジェクトを返します。 (それ以外の場合はnullを返します。)
  • 次に、コードはsnapshot.hasDataを使用して、ストリームの値にUserオブジェクトが含まれているかどうかを確認します。
  • 存在しない場合は、 SignInScreenウィジェットが返されます。現時点では、その画面では何も行われません。これは次のステップで更新されます。
  • それ以外の場合は、認証されたユーザーのみがアクセスできるアプリケーションの主要部分であるHomeScreenを返します。

SignInScreen 、FlutterFire UI パッケージに含まれるウィジェットです。これが、このコードラボの次のステップの焦点になります。この時点でアプリを実行すると、空のサインイン画面が表示されるはずです。

5. サインイン画面

FlutterFire UI によって提供されるSignInScreenウィジェットは、次の機能を追加します。

  • ユーザーにサインインを許可します
  • ユーザーがパスワードを忘れた場合は、「パスワードを忘れた場合」をタップします。パスワードをリセットするためのフォームが表示されます
  • ユーザーがまだ登録していない場合は、「登録」をタップすると、サインアップできる別のフォームが表示されます。

繰り返しますが、これに必要なコードは数行だけです。 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();
      },
    );
  }
}

SignInScreenウィジェットとそのproviders引数は、前述のすべての機能を取得するために必要な唯一のコードです。 「電子メール」と「パスワード」のテキスト入力と「サインイン」ボタンを含むサインイン画面が表示されます。

機能的ではありますが、スタイルが欠けています。ウィジェットは、サインイン画面の外観をカスタマイズするためのパラメーターを公開します。たとえば、会社のロゴを追加したい場合があります。

サインイン画面をカスタマイズする

ヘッダービルダー

SignInScreen.headerBuilder引数を使用すると、サインイン フォームの上に必要なウィジェットを追加できます。次のコードで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: [
             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();
     },
   );
 }
}

headerBuilder 引数には、FlutterFire UI パッケージで定義されている HeaderBuilder タイプの関数が必要です。

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

これはコールバックであるため、 BuildContextBoxConstraintsなどの使用できる値を公開し、ウィジェットを返す必要があります。どのウィジェットを返しても、画面の上部に表示されます。この例では、新しいコードにより画面の上部に画像が追加されます。アプリケーションは次のようになっているはずです。

73d7548d91bbd2ab.png

字幕ビルダー

サインイン画面では、画面をカスタマイズできる 3 つの追加パラメーター ( subtitleBuilderfooterBuilder 、およびsideBuilder ) が公開されています。

subtitleBuilderコールバック引数にAuthAction型のアクションが含まれるという点で少し異なります。 AuthActionは、ユーザーがいる画面が「サインイン」画面であるか「登録」画面であるかを検出するために使用できる列挙型です。

auth_gate.dart 内のコードを更新して、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();
     },
   );
 }
}

アプリケーションをリロードすると、次のようになります。

footerBuilder 引数は、subtitleBuilder と同じです。これは画像ではなくテキストを対象としているため、 BoxConstraintsshrinkOffsetは公開されません。 (ただし、必要なウィジェットを追加できます。)

このコードを使用して、サインイン画面にフッターを追加します。

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

サイドビルダー

SignInScreen.sidebuilder 引数はコールバックを受け入れます。今回のコールバックへの引数はBuildContextdouble shrinkOffsetです。 SideBuilder が返すウィジェットは、サインイン フォームの左側に、ワイド スクリーンにのみ表示されます。これは事実上、ウィジェットがデスクトップと Web アプリにのみ表示されることを意味します。

FlutterFire UI は内部的にブレークポイントを使用して、ヘッダー コンテンツを表示するか (モバイルなどの縦長の画面)、サイド コンテンツを表示するか (ワイド スクリーン、デスクトップ、または Web) を決定します。具体的には、画面の幅が 800 ピクセルを超える場合、サイド ビルダー コンテンツが表示され、ヘッダー コンテンツは表示されません。画面の幅が 800 ピクセル未満の場合は、その逆が当てはまります。

auth_gate.dart のコードを更新して、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();
     },
   );
 }
}

ウィンドウの幅を拡大すると、アプリは次のように表示されるはずです (Flutter Web または MacOS を使用している場合)。

8dc60b4e5d7dd2d0.png

ユーザーを作成する

この時点で、この画面のコードはすべて完了しました。ただし、サインインする前に、ユーザーを作成する必要があります。これは「登録」画面で行うことも、Firebase コンソールでユーザーを作成することもできます。

コンソールを使用するには:

  1. Firebase コンソールの「ユーザー」テーブルに移動します。
  2. ここをクリック
  3. 「flutterfire-ui-codelab」(別の名前を使用した場合は別のプロジェクト) を選択します。次の表が表示されます。

f038fd9a58ed60d9.png

  1. 「ユーザーを追加」ボタンをクリックします。

2d78390d4c5dbbfa.png

  1. 新しいユーザーの電子メール アドレスとパスワードを入力します。下の画像で入力したように、これは偽の電子メールとパスワードである可能性があります。これは機能しますが、偽の電子メール アドレスを使用すると、「パスワードを忘れた場合」機能は機能しません。

62ba0feb33d54追加.png

  1. 「ユーザーを追加」をクリックします

32b236b3ef94d4c7.png

これで、Flutter アプリケーションに戻り、サインイン ページからユーザーをサインインできます。アプリは次のようになります。

dd43d260537f3b1a.png

6.プロフィール画面

FlutterFire UI にはProfileScreenウィジェットも用意されており、これも数行のコードで多くの機能を提供します。

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) => const ProfileScreen(),
                ),
              );
            },
          )
        ],
        automaticallyImplyLeading: false,
      ),
      body: Center(
        child: Column(
          children: [
            Image.asset('dash.png'),
            Text(
              'Welcome!',
              style: Theme.of(context).textTheme.displaySmall,
            ),
            const SignOutButton(),
          ],
        ),
      ),
    );
  }
}

注目すべき新しいコードは、 IconButton.isPressed method.そのIconButton押されると、アプリケーションは新しい匿名ルートを作成し、そこに移動します。このルートには、 MaterialPageRoute.builderコールバックから返されるProfileScreenウィジェットが表示されます。

アプリをリロードし、右上 (アプリバー内) のアイコンを押すと、次のようなページが表示されます。

36487fc4ab4f26a7.png

これは、FlutterFire UI ページによって提供される標準 UI です。すべてのボタンとテキスト フィールドは Firebase Auth に接続されており、そのまま使用できます。たとえば、「名前」テキストフィールドに名前を入力すると、FlutterFire UI がFirebaseAuth.instance.currentUser?.updateDisplayNameメソッドを呼び出し、その名前を Firebase に保存します。

サインアウトする

現時点では「サインアウト」ボタンを押してもアプリは変わりません。サインアウトされますが、AuthGate ウィジェットには戻りません。これを実装するには、ProfileScreen.actions パラメーターを使用します。

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

ここで、 ProfileScreenのインスタンスを作成するときに、アクションのリストもProfileScreen.actions引数に渡します。これらのアクションのタイプはFlutterFireUiActionです。 FlutterFireUiActionのサブタイプであるさまざまなクラスが多数あり、通常はこれらを使用して、さまざまな認証状態の変更に反応するようにアプリに指示します。 SignedOutAction は、Firebase 認証状態が currentUser が null に変化したときに指定するコールバック関数を呼び出します。

SignedOutAction がトリガーされたときにNavigator.of(context).pop()を呼び出すコールバックを追加すると、アプリは前のページに移動します。このサンプル アプリでは、永続的なルートが 1 つだけあり、サインインしているユーザーがいない場合はサインイン ページが表示され、ユーザーがいる場合はホームページが表示されます。これはユーザーがサインアウトすると発生するため、アプリにはサインイン ページが表示されます。

プロフィールページをカスタマイズする

サインイン ページと同様に、プロフィール ページもカスタマイズ可能です。まず、ユーザーがプロフィール ページにアクセスすると、現在のページにはホーム ページに戻る方法がありません。これを修正するには、ProfileScreen ウィジェットに AppBar を追加します。

ホーム.ダーツ

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

ProfileScreen.appBar引数は Flutter マテリアル パッケージからAppBarウィジェットを受け入れるため、構築してScaffoldに渡した他のAppBarと同様に扱うことができます。この例では、「戻る」ボタンを自動的に追加するデフォルトの機能が維持され、画面にタイトルが付けられています。

プロフィール画面に子供を追加する

ProfileScreen ウィジェットには、children という名前のオプションの引数もあります。この引数はウィジェットのリストを受け取り、それらのウィジェットは、ProfileScreen を構築するために内部ですでに使用されている列ウィジェットの内側に垂直に配置されます。 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();
                      })
                    ],
                    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(),
          ],
        ),
      ),
    );
  }
}

アプリをリロードすると、画面に次の内容が表示されます。

ebe5792b765dbf87.png

7. マルチプラットフォームの Google 認証サインイン

FlutterFire UI は、Google、Twitter、Facebook、Apple、Github などのサードパーティ プロバイダーで認証するためのウィジェットと機能も提供します。

Google 認証と統合するには、ネイティブ認証フローを処理する公式のfirebase_ui_oauth_googleプラグインとその依存関係をインストールします。ターミナルで、flutter プロジェクトのルートに移動し、次のコマンドを入力します。

flutter pub add google_sign_in
flutter pub add firebase_ui_oauth_google

Google サインイン プロバイダーを有効にする

次に、 Firebase コンソールで Google プロバイダを有効にします。

  1. コンソールの「認証サインインプロバイダー」画面に移動します。
  2. 「新しいプロバイダーを追加」をクリックします。 8286fb28be94bf30.png
  3. 「Google」を選択します。 c4e28e6f4974be7f.png
  4. 「有効」というラベルの付いたスイッチを切り替えて、「保存」を押します。 e74ff86990763826.png
  5. 設定ファイルのダウンロードに関する情報を示すモーダルが表示されたら、「完了」をクリックします。
  6. Google サインイン プロバイダーが追加されたことを確認します。 5329ce0543c90d95.png

Googleサインインボタンを追加

Google サインインを有効にして、様式化された Google サインイン ボタンをサインイン ページに表示するために必要なウィジェットを追加します。 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: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();
     },
   );
 }
}

ここでの唯一の新しいコードはGoogleProvider(clientId: "YOUR_WEBCLIENT_ID")を SignInScreen ウィジェット構成に追加することです。

これを追加してアプリをリロードすると、Google サインイン ボタンが表示されます。

aca71a46a011bfb5.png

サインインボタンを構成する

追加の設定を行わないとボタンは機能しません。 Flutter Web を使用して開発している場合、これが機能するために追加する必要がある唯一の手順です。他のプラットフォームでは追加の手順が必要ですが、これについては後で少し説明します。

  1. Firebase コンソールの [認証プロバイダ] ページに移動します。
  2. Google プロバイダーをクリックします。 9b3a325c5eca6e49.png
  3. 「Web SDK 構成」展開パネルをクリックします。
  4. 「Web クライアント ID」から値をコピーします。 711a79f0d931c60f.png
  5. テキスト エディタに戻り、この ID をclientId名前付きパラメータに渡して、ファイルauth_gate.dart内のGoogleProviderのインスタンスを更新します。
GoogleProvider(
   clientId: "YOUR_WEBCLIENT_ID"
)

Web クライアント ID を入力したら、アプリをリロードします。 [Google でサインイン] ボタンを押すと、(Web を使用している場合) 新しいウィンドウが表示され、Google サインイン フローが表示されます。最初は次のようになります。

14e73e3c9de704bb.png

iOSの設定

これを iOS で動作させるには、追加の構成プロセスが必要です。

  1. Firebase コンソールの [プロジェクト設定] 画面に移動します。次のような Firebase アプリをリストするカードが表示されます。 fefa674acbf213cc.png
  2. iOSをクリックします。あなたのアプリケーション名は私のものとは異なることに注意してください。 flutter-codelabs/firebase-auth-flutterfire-ui/startプロジェクトを使用してこのコードラボを実行した場合、私の場合は「完了」と表示されますが、あなたのものでは「開始」と表示されます。
  3. 「GoogleServices-Info.plist」というボタンをクリックして、必要な構成ファイルをダウンロードします。 f89b3192871dfbe3.png
  4. ダウンロードしたファイルを というディレクトリにドラッグ アンド ドロップします。 Flutter プロジェクトの/ios/Runner
  5. プロジェクトのルートから次のターミナル コマンドを実行して、Xcode を開きます。

ios/Runner.xcworkspace を開く

  1. Runner ディレクトリを右クリックし、「Runner」にファイルを追加を選択します。 858986063a4c5201.png
  2. ファイルマネージャーからGoogleService-Info.plistを選択します。
  3. テキスト エディター (Xcode ではありません) に戻り、以下の CFBundleURLTypes 属性を [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 -->

Flutter アプリがすでに iOS で実行されている場合は、完全にシャットダウンしてからアプリケーションを再実行する必要があります。それ以外の場合は、iOS でアプリを実行します。

8. おめでとうございます!

Flutter コードラボの Firebase Auth UI が完了しました。このコードラボの完成したコードは、github の「complete」ディレクトリにあります: Flutter Codelabs

私たちがカバーした内容

  • Firebase を使用するための Flutter アプリのセットアップ
  • Firebase コンソールでの Firebase プロジェクトのセットアップ
  • FlutterFire CLI
  • Firebase CLI
  • Firebase認証の使用
  • FlutterFire UI を使用して Flutter アプリで Firebase 認証を簡単に処理する

次のステップ

もっと詳しく知る

スパーキーはあなたと一緒にお祝いするためにここにいます!

2a0ad195769368b1.gif