この Codelab について
1. 始める前に
この Codelab では、FlutterFire UI パッケージを使用して Firebase Authentication を Flutter アプリに追加する方法を学びます。このパッケージを使用すると、メール/パスワード認証と Google ログイン認証の両方を Flutter アプリに追加できます。また、Firebase プロジェクトを設定し、FlutterFire CLI を使用して Flutter アプリで Firebase を初期化する方法も学びます。
前提条件
この Codelab は、Flutter の使用経験があることを前提としています。まだの場合は、まず基本的な使い方を学習してください。次のリンクが役に立ちます。
Firebase の使用経験も必要ですが、Flutter プロジェクトに Firebase を追加したことがない方でも問題ありません。Firebase コンソールについてよく知らない場合や、Firebase を初めて使用する場合は、まず次のリンクをご覧ください。
作成するアプリの概要
この Codelab では、Firebase for Authentication を使用して Flutter アプリの認証フローを構築する方法について説明します。アプリには、ログイン画面、[登録] 画面、パスワード復元画面、ユーザー プロフィール画面があります。
学習内容
この Codelab では次のことを学びます。
- 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
パッケージを使用してユーザー プロフィール画面をアプリに追加する
この Codelab では、firebase_ui_auth
パッケージを使用して堅牢な認証システムを追加することに焦点を当てます。ご覧のとおり、上記のすべての機能を備えたこのアプリ全体は、約 100 行のコードで実装できます。
必要なもの
- Flutter とインストールされている SDK に関する知識
- テキスト エディタ(JetBrains IDE、Android Studio、VS Code は Flutter でサポートされています)
- Google Chrome ブラウザ、または Flutter の他の開発ターゲット。(この Codelab の一部のターミナル コマンドは、Chrome でアプリを実行していることを前提としています)。
2. Firebase プロジェクトを作成して設定する
まず、Firebase のウェブコンソールで Firebase プロジェクトを作成します。
Firebase プロジェクトを作成する
- Firebase にログインします。
- Firebase コンソールで [プロジェクトを追加](または [プロジェクトを作成])をクリックし、Firebase プロジェクトの名前を入力します(例: FlutterFire-UI-Codelab)。
- プロジェクト作成オプションをクリックします。プロンプトが表示されたら、Firebase の利用規約に同意します。このアプリではアナリティクスを使用しないため、Google アナリティクスの設定はスキップします。
Firebase プロジェクトの詳細については、Firebase プロジェクトについて理解するをご覧ください。
Firebase Authentication でメールによるログインを有効にする
作成するアプリは、Firebase Authentication を使用してユーザーがアプリにログインできるようにします。また、Flutter アプリケーションから新規ユーザーを登録することもできます。
Firebase Authentication は Firebase コンソールを使用して有効にする必要があります。有効にしたら、特別な設定が必要になります。
ユーザーがウェブアプリにログインできるようにするには、まずメール/パスワードのログイン方法を使用します。後で、Google ログイン メソッドを追加します。
- Firebase コンソールの左側のパネルで [Build] メニューを開きます。
- [認証] をクリックし、[使ってみる] ボタン、[ログイン方法] タブの順にクリックします(または、ここをクリックして [ログイン方法] タブに直接移動します)。
- [ログイン プロバイダ] リストで [メール/パスワード] をクリックし、[有効にする] スイッチをオンの位置に設定して、[保存] をクリックします。
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
ディレクトリに作成する必要があります。このディレクトリには、Codelab のコレクションのコードが含まれています。この Codelab のコードはサブディレクトリ flutter-codelabs/firebase-auth-flutterfire-ui
にあります。
ディレクトリ flutter-codelabs/firebase-auth-flutterfire-ui
には 2 つの Flutter プロジェクトが含まれています。一つは complete
、もう一つは start
という名前にします。start
ディレクトリには未完成のプロジェクトが含まれています。ここで最も多くの時間を費やすことになります。
cd flutter-codelabs/firebase-auth-flutterfire-ui/start
先に進む場合や、完成した状態を確認したい場合は、complete という名前のディレクトリで相互参照してください。
Codelab に沿って自分でコードを追加する場合は、flutter-codelabs/firebase-auth-flutterfire-ui/start
にある Flutter アプリから始め、Codelab 全体でそのプロジェクトにコードを追加する必要があります。そのディレクトリを開くか、お好みの IDE にインポートします。
Firebase CLI のインストール
Firebase CLI には、Firebase プロジェクトを管理するためのツールが用意されています。CLI は FlutterFire CLI に必要で、後でインストールします。
CLI をインストールする方法はいくつかあります。macOS または Linux を使用している場合は、ターミナルから次のコマンドを実行するのが最も簡単な方法です。
curl -sL https://firebase.tools | bash
CLI をインストールしたら、Firebase で認証する必要があります。
- Google アカウントで Firebase にログインするには、次のコマンドを実行します。
firebase login
- このコマンドにより、ローカルマシンが Firebase に接続し、Firebase プロジェクトへのアクセスが許可されます。
- Firebase プロジェクトを一覧表示し、CLI が正しくインストールされていて、アカウントにアクセスできることをテストします。次のコマンドを実行します。
firebase projects:list
- 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 プロジェクトと設定するプラットフォームを選択するように求められます。
次のスクリーンショットは、回答が必要なプロンプトを示しています。
- 使用するプロジェクトを選択します。この場合は、
flutterfire-ui-codelab
を使用します。
- 使用するプラットフォームを選択します。この Codelab では、ウェブ、iOS、Android 向けに Firebase Authentication for Flutter を構成する手順を説明しますが、すべてのオプションを使用するように Firebase プロジェクトを設定することもできます。
- このスクリーンショットは、プロセスの終了時の出力を示しています。Firebase に精通している方は、コンソールでプラットフォーム アプリケーション(Android アプリケーションなど)を作成する必要がなかったことに気付くでしょう。これは、FlutterFire CLI が自動的に作成したものです。
完了したら、テキスト エディタで Flutter アプリを確認します。FlutterFire CLI によって firebase_options.dart
という新しいファイルが生成されました。このファイルには、FirebaseOptions というクラスが含まれています。このクラスには、各プラットフォームに必要な Firebase 構成を保持する静的変数があります。flutterfire configure
の実行時にすべてのプラットフォームを選択した場合は、web
、android
、ios
、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 では、Firebase プロジェクト内の特定のプラットフォームの特定のビルドを指すために「アプリケーション」という用語を使用します。たとえば、FlutterFire-ui-codelab という Firebase プロジェクトには、Android 用、iOS 用、macOS 用、ウェブ用の複数のアプリがあります。
メソッド DefaultFirebaseOptions.currentPlatform
は、Flutter で公開されている TargetPlatform
列挙型を使用して、アプリが実行されているプラットフォームを検出し、正しい Firebase アプリケーションに必要な Firebase 構成値を返します。
Flutter アプリに Firebase パッケージを追加する
設定の最後のステップは、関連する 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
関数のコードを更新します。
main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}
このコードは次の 2 つの処理を行います。
WidgetsFlutterBinding.ensureInitialized()
は、Flutter フレームワークが完全に起動されるまで、アプリケーション ウィジェット コードの実行を開始しないように Flutter に指示します。Firebase はネイティブ プラットフォーム チャネルを使用します。このチャネルではフレームワークの実行が必要です。Firebase.initializeApp
は、Flutter アプリと Firebase プロジェクト間の接続を設定します。DefaultFirebaseOptions.currentPlatform
は、生成されたfirebase_options.dart
ファイルからインポートされます。この静的値は、実行されているプラットフォームを検出し、対応する Firebase キーを渡します。
4. 最初の Firebase UI Auth ページを追加
Firebase UI for Auth には、アプリケーションの画面全体を表すウィジェットが用意されています。これらの画面は、ログイン、登録、パスワードの忘れた、ユーザー プロフィールなど、アプリケーション全体のさまざまな認証フローを処理します。まず、メイン アプリケーションの認証ガードとして機能するランディング ページをアプリに追加します。
マテリアル アプリまたは Cupertino アプリ
FlutterFire UI では、アプリを MaterialApp または CupertinoApp でラップする必要があります。選択した内容に応じて、マテリアル ウィジェットと Cupertino ウィジェットの違いが UI に自動的に反映されます。この Codelab では、app.dart
でアプリにすでに追加されている MaterialApp
を使用します。
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(),
);
}
}
認証ステータスを確認する
ログイン画面を表示する前に、ユーザーが現在認証されているかどうかを判断する必要があります。最も一般的な確認方法は、Firebase Auth プラグインを使用して FirebaseAuth の authStateChanges をリッスンすることです。
上記のコードサンプルでは、MaterialApp
は build メソッドで AuthGate
ウィジェットを作成しています。(これはカスタム ウィジェットで、FlutterFire UI では提供されていません)。
このウィジェットを更新して、authStateChanges
ストリームを含める必要があります。
authStateChanges
API は、現在のユーザー(ログインしている場合)を含む Stream
を返します。ログインしていない場合は null を返します。アプリでこの状態をサブスクライブするには、Flutter の StreamBuilder ウィジェットを使用してストリームを渡します。
StreamBuilder
は、渡された Stream のデータの最新のスナップショットに基づいてビルドされるウィジェットです。ストリームが新しいスナップショットを出力すると、自動的に再ビルドされます。
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
が渡されます。このデータは、ユーザーが認証されている場合に FirebaseUser
オブジェクトを返します。(それ以外の場合はnull
を返します)。- 次に、コードは
snapshot.hasData
を使用して、ストリームの値にUser
オブジェクトが含まれているかどうかを確認します。 - 存在しない場合は、
SignInScreen
ウィジェットが返されます。現在のところ、この画面は何も機能しません。これは次のステップで更新します。 - それ以外の場合は、
HomeScreen
を返します。これは、認証されたユーザーのみがアクセスできるアプリケーションのメイン部分です。
SignInScreen
は、FlutterFire UI パッケージのウィジェットです。この Codelab の次のステップでは、この点について詳しく説明します。この時点でアプリを実行すると、空白のログイン画面が表示されます。
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
引数のみです。メールアドレスとパスワードのテキスト入力欄と [ログイン] ボタンが表示されたログイン画面が表示されます。
機能は問題ありませんが、スタイルが設定されていません。このウィジェットには、ログイン画面の外観をカスタマイズするためのパラメータが公開されています。たとえば、会社のロゴを追加できます。
ログイン画面をカスタマイズする
headerBuilder
SignInScreen.headerBuilder
引数を使用すると、ログイン フォームの上に任意のウィジェットを追加できます。このウィジェットは、モバイル デバイスなどの狭い画面にのみ表示されます。ワイド画面では、SignInScreen.sideBuilder
を使用できます。これはこの Codelab の後半で説明します。
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,
);
コールバックであるため、BuildContext
や BoxConstraints
などの使用可能な値が公開され、ウィジェットを返す必要があります。返されたウィジェットは画面上部に表示されます。この例では、新しいコードによって画面の上部に画像が追加されます。アプリケーションは次のようになります。
字幕ビルダー
ログイン画面には、画面をカスタマイズできる 3 つのパラメータ(subtitleBuilder
、footerBuilder
、sideBuilder
)が追加されています。
subtitleBuilder
は、コールバック引数に AuthAction
タイプのアクションが含まれているという点で、少し異なります。AuthAction
は、ユーザーが現在表示している画面が「ログイン」画面か「登録」画面かを検出するために使用できる列挙型です。
subtitleBuilder を使用するように 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('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 と同じです。画像ではなくテキストを対象としているため、BoxConstraints
や shrinkOffset
は公開されません。(ただし、任意のウィジェットを追加できます)。
次のコードを使用して、ログイン画面にフッターを追加します。
auth_gate.dart
import 'package:firebase_auth/firebase_auth.dart' hide EmailAuthProvider;
import 'package:firebase_ui_auth/firebase_ui_auth.dart';
import 'package:flutter/material.dart';
import 'home.dart';
class AuthGate extends StatelessWidget {
const AuthGate({super.key});
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return SignInScreen(
providers: [
EmailAuthProvider()
],
headerBuilder: (context, constraints, shrinkOffset) {
return Padding(
padding: const EdgeInsets.all(20),
child: AspectRatio(
aspectRatio: 1,
child: Image.asset('flutterfire_300x.png'),
),
);
},
subtitleBuilder: (context, action) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: action == AuthAction.signIn
? const Text('Welcome to FlutterFire, please sign in!')
: const Text('Welcome to Flutterfire, please sign up!'),
);
},
footerBuilder: (context, action) {
return const Padding(
padding: EdgeInsets.only(top: 16),
child: Text(
'By signing in, you agree to our terms and conditions.',
style: TextStyle(color: Colors.grey),
),
);
},
);
}
return const HomeScreen();
},
);
}
}
Side Builder
SignInScreen.sidebuilder 引数はコールバックを受け入れます。この場合、そのコールバックの引数は BuildContext
と double shrinkOffset
です。sideBuilder が返すウィジェットは、ログイン フォームの左側に表示されます(ワイド画面の場合のみ)。つまり、ウィジェットはパソコンとウェブアプリでのみ表示されます。
FlutterFire UI は内部でブレークポイントを使用して、ヘッダー コンテンツを表示する必要があるかどうか(モバイルなどの縦長画面の場合)と、サイド コンテンツを表示する必要があるかどうか(横長画面、パソコン、ウェブの場合)を判断します。具体的には、画面の幅が 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 ウェブまたは macOS を使用している場合)。
ユーザーを作成する
これで、この画面のコードはすべて完成しました。ただし、ログインする前に、ユーザーを作成する必要があります。これは [登録] 画面で行うことができます。また、Firebase コンソールでユーザーを作成することもできます。
コンソールを使用するには:
- Firebase コンソールの [ユーザー] テーブルに移動します。
- こちらをクリック
- [flutterfire-ui-codelab](または別の名前を使用した場合は別のプロジェクト)を選択します。次の表が表示されます。
- [ユーザーを追加] ボタンをクリックします。
- 新しいユーザーのメールアドレスとパスワードを入力します。以下の画像に入力したように、メールアドレスとパスワードは偽のものでかまいません。使用できますが、偽のメールアドレスを使用すると [パスワードをお忘れの場合] 機能は使用できません。
- [ユーザーを追加] をクリックします。
これで、Flutter アプリに戻り、ログインページからユーザーをログインさせることができます。アプリの表示は次のようになります。
6. プロフィール画面
FlutterFire UI には ProfileScreen
ウィジェットも用意されています。これも、数行のコードで多くの機能を利用できます。
ProfileScreen ウィジェットを追加
テキスト エディタで 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) => 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
メソッドに渡されるコールバックです。その IconButton
が押されると、アプリケーションは新しい匿名ルートを作成して、そのルートに移動します。このルートには、MaterialPageRoute.builder
コールバックから返された ProfileScreen
ウィジェットが表示されます。
アプリを再読み込みし、右上(アプリバー内)のアイコンを押すと、次のようなページが表示されます。
これは、FlutterFire UI ページで提供される標準の UI です。すべてのボタンとテキスト フィールドは Firebase Auth に接続されており、すぐに使用できます。たとえば、[名前] テキスト フィールドに名前を入力すると、FlutterFire UI が FirebaseAuth.instance.currentUser?.updateDisplayName
メソッドを呼び出し、その名前が Firebase に保存されます。
ログアウト
現在、[ログアウト] ボタンを押してもアプリは変更されません。ログアウトされますが、AuthGate ウィジェットには戻りません。これを実装するには、ProfileScreen.actions パラメータを使用します。
まず、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(),
],
),
),
);
}
}
ProfileScreen
のインスタンスを作成するときに、アクションのリストを ProfileScreen.actions
引数に渡すようにします。これらのアクションは FlutterFireUiAction
型です。FlutterFireUiAction
のサブタイプにはさまざまなクラスがあり、通常は、さまざまな認証状態の変化に応答するようにアプリに指示するために使用します。SignedOutAction は、Firebase Auth の状態が currentUser が null になるように変更されたときに、指定したコールバック関数を呼び出します。
SignedOutAction がトリガーされたときに Navigator.of(context).pop()
を呼び出すコールバックを追加すると、アプリは前のページに移動します。このサンプルアプリでは、永続的なルートは 1 つだけです。ログインしていないユーザーの場合はログインページが表示され、ログインしているユーザーの場合はホームページが表示されます。これはユーザーがログアウトしたときに発生するため、アプリにはログインページが表示されます。
プロフィール ページをカスタマイズする
ログインページと同様に、プロフィール ページはカスタマイズ可能です。まず、現在のページでは、ユーザーがプロフィール ページに移動した後にホームページに戻る方法がありません。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(),
],
),
),
);
}
}
ProfileScreen.appBar
引数は Flutter マテリアル パッケージの AppBar
ウィジェットを受け取るため、ビルドして Scaffold
に渡した他の AppBar
と同様に扱うことができます。この例では、「戻る」ボタンを自動的に追加するデフォルトの機能は保持され、画面にタイトルが追加されています。
プロフィール画面にお子様を追加する
ProfileScreen ウィジェットには、children という名前のオプション パラメータもあります。この引数にはウィジェットのリストを指定します。これらのウィジェットは、ProfileScreen の作成に内部で使用されている Column ウィジェットの内部に縦方向に配置されます。ProfileScreen の build メソッドにあるこの Column ウィジェットは、渡された子を [ログアウト] ボタンの上に配置します。
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(
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(),
],
),
),
);
}
}
アプリを再読み込みすると、画面に次のように表示されます。
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 プロバイダを有効にします。
- コンソールで [認証ログイン プロバイダ] 画面に移動します。
- [新しいプロバイダを追加] をクリックします。
- [Google] を選択します。
- [有効にする] のスイッチを切り替えて、[保存] を押します。
- 構成ファイルのダウンロードに関する情報が表示されたモーダルが表示されたら、[完了] をクリックします。
- Google ログイン プロバイダが追加されていることを確認します。
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();
},
);
}
}
新しいコードは、SignInScreen ウィジェットの構成に GoogleProvider(clientId: "YOUR_WEBCLIENT_ID")
を追加した点のみです。
追加したら、アプリを再読み込みすると、Google ログイン ボタンが表示されます。
ログイン設定ボタン
追加の設定なしではボタンが機能しません。Flutter Web で開発している場合は、このステップを追加するだけで、この機能が動作します。他のプラットフォームでは追加の手順が必要になります。この点については後述します。
- Firebase コンソールで [認証プロバイダ] ページに移動します。
- Google プロバイダをクリックします。
- [ウェブ SDK 構成] 展開パネルをクリックします。
- [ウェブ クライアント ID]
の値をコピーします。
- テキスト エディタに戻り、この ID を
clientId
という名前のパラメータに渡して、ファイルauth_gate.dart
のGoogleProvider
のインスタンスを更新します。
GoogleProvider(
clientId: "YOUR_WEBCLIENT_ID"
)
ウェブ クライアント ID を入力したら、アプリを再読み込みします。[Google でログイン] ボタンを押すと、新しいウィンドウが表示されます(ウェブを使用している場合)。このウィンドウには、Google ログイン フローの手順が表示されます。最初は次のようになります。
iOS の構成
iOS でこの機能を使用するには、追加の設定プロセスが必要です。
- Firebase コンソールで [プロジェクトの設定] 画面に移動します。Firebase アプリが一覧表示されたカードが表示されます。カードは
のように表示されます。
- [iOS] をクリックします。アプリケーション名は、ここで使用している名前とは異なります。
flutter-codelabs/firebase-auth-flutterfire-ui/start
プロジェクトを使用してこの Codelab を進めた場合、私の「complete」は「start」になります。 - [GoogleServices-Info.plist] ボタンをクリックして、必要な構成ファイルをダウンロードします。
- ダウンロードしたファイルを というディレクトリにドラッグ&ドロップします。Flutter プロジェクトの
/ios/Runner
。 - プロジェクトのルートから
open ios/Runner.xcworkspace
というターミナル コマンドを実行して Xcode を開きます。 - Runner ディレクトリを右クリックし、[Add Files to "Runner"] を選択します。
- ファイル マネージャーから GoogleService-Info.plist を選択します。
- テキスト エディタ(Xcode 以外)に戻り、[my_project]/ios/Runner/Info.plist ファイルに以下の CFBundleURLTypes 属性を追加します。
<!-- 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 -->
- ウェブでの設定で追加した
GoogleProvider.clientId
は、Firebase iOS クライアント ID に関連付けられているクライアント ID に置き換える必要があります。まず、この ID はfirebase_options.dart
ファイルのiOS
定数の一部として確認できます。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',
);
- その値を
AuthGate
ウィジェットのGoogleProvider.clientId
引数に貼り付けます。
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();
},
);
}
}
Flutter アプリがすでに iOS で実行されている場合は、完全にシャットダウンしてからアプリを再実行する必要があります。それ以外の場合は、iOS でアプリを実行します。
8. お疲れさまでした
これで、Flutter 向け Firebase Auth UI の Codelab は終了です。この Codelab の最終的なコードは、GitHub の「complete」ディレクトリ(Flutter Codelabs)にあります。
学習した内容
- Firebase を使用するように Flutter アプリを設定する
- Firebase コンソールで Firebase プロジェクトを設定する
- FlutterFire CLI
- Firebase CLI
- Firebase Authentication の使用
- FlutterFire UI を使用して Flutter アプリで Firebase Authentication を簡単に処理する
次のステップ
- Flutter で Firestore と Authentication を使用する方法の詳細については、Firebase for Flutter を理解する Codelab をご覧ください。
- Flutter アプリケーションの構築に役立つ他の Firebase ツールについて確認する。
- Cloud Storage
- Cloud Functions
- Realtime Database
詳細
- Firebase サイト: firebase.google.com
- Flutter サイト: flutter.dev
- FlutterFire Firebase Flutter ウィジェット: firebase.flutter.dev
- Firebase の YouTube チャンネル
- Flutter の YouTube チャンネル
スパーキーがあなたのお祝いに参加します。