注意事項
この記事は、Notion AIに対して
- 問題と解決策の概要
- 例示用のコード
を渡して生成した実験的な記事になります。
はじめに
FlutterとFirebaseを使用してGoogle認証を導入する方法について説明します。
Google認証を導入することで、ユーザーが簡単にアプリにログインできるようになります。
本記事では、FlutterとFirebaseを使用してGoogle認証を導入するためのステップバイステップの手順をご紹介します。
事前準備
事前に以下のツールがインストールされていることが前提です。
アプリの画面構成
今回作るアプリの画面は2つで、それぞれの画面は以下のように定義しておきます。
- Login
- 未ログインであれば表示する画面
- ログインボタンがあり、ログインが成功したらHome画面へ遷移する
- Home
- ログイン済みであれば表示する画面
- ログアウトボタンがあり、ログアウトが成功したらLogin画面へ遷移する
Google認証を導入したFlutterアプリの作成
Firebaseプロジェクトの作成
Firebaseプロジェクトを作成し、Google認証できるように準備します。
- Firebase Consoleにログインし、プロジェクトを作成する
Authentication
を有効化するSign-in method
でGoogleを有効化にする
Flutterプロジェクトの作成
Flutterアプリのためにプロジェクトを作成します。
新しいFlutterプロジェクトを悪性する
flutter create flutter-auth-sample
FlutterFireのセットアップ
FlutterでFirebaseを使えるようにするためのCLIツールFlutterFire CLIをインストールします。
FlutterFire CLIをグローバルにインストールする
dart pub global activate flutterfire_cli
FlutterFire CLIを使用して設定する
fluterfire configure
Firebase Authenticationを使用するために必要なライブラリを追加する
flutter pub add firebase_core firebase_auth
Firebaseの初期化処理の追加
Flutterアプリの起動時にFirebaseの初期化処理を追加します。
Firebase用のパッケージを追加する
import 'package:firebase_core/firebase_core.dart';
main関数を非同期にし、Firebaseの初期化処理を行う
// Before void main() { runApp(const MyApp()); } // After Future<void> main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); await Firebase.initializeApp(); runApp(const MyApp()); }
Login画面の作成
Login画面を作成します。 この画面は、以下のような要件が存在します。
- Login
- 未ログインであれば表示する画面
- ログインボタンがあり、ログインが成功したらHome画面へ遷移する
今の段階では、ボタンは配置のみだけにしログイン処理の実装は除外します。
Login画面のWidgetを作成する
class LoginPage extends StatefulWidget { static String routeName() => '/login'; const LoginPage({super.key}); @override State<LoginPage> createState() => _LoginPageState(); } class _LoginPageState extends State<LoginPage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Login Page')), body: Center( // Google Sign-in child: ElevatedButton( child: const Text('Google Sign-in'), onPressed: () {}, ), ), ); } }
アプリ起動時にLogin画面が表示されるようにMyAppを書き換える
class MyApp extends StatelessWidget { const MyApp({super.key}); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Authentication Demo', debugShowCheckedModeBanner: false, theme: ThemeData.dark(), initialRoute: LoginPage.routeName(), routes: { LoginPage.routeName(): (context) => const LoginPage(), }, ); } }
アプリを起動してエラーが出ずに表示されることを確認する
Home画面の作成
Home画面を作成します。 この画面は、以下のような要件が存在します。
- Home
- ログイン済みであれば表示する画面
- ログアウトボタンがあり、ログアウトが成功したらLogin画面へ遷移する
今の段階では、ボタンは配置のみだけにしログアウト処理の実装は除外します。
Home画面のWidgetを作成する
class HomePage extends StatefulWidget { static String routeName() => '/home'; const HomePage({super.key}); @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Home Page')), body: Center( child: ElevatedButton( child: const Text('Logout'), onPressed: () {}, ), ), ); } }
アプリ起動時にLogin画面が表示されるようにMyAppを書き換える
class MyApp extends StatelessWidget { const MyApp({super.key}); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Authentication Demo', debugShowCheckedModeBanner: false, theme: ThemeData.dark(), initialRoute: HomePage.routeName(), // <- ここを書き換え routes: { LoginPage.routeName(): (context) => const LoginPage(), HomePage.routeName(): (context) => const HomePage(), // <- 追記 }, ); } }
アプリを起動してエラーが出ずに表示されることを確認する
initialRouteをLogin画面に戻しておく
class MyApp extends StatelessWidget { const MyApp({super.key}); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Authentication Demo', debugShowCheckedModeBanner: false, theme: ThemeData.dark(), initialRoute: LoginPage.routeName(), // <- ここを書き換え routes: { LoginPage.routeName(): (context) => const LoginPage(), HomePage.routeName(): (context) => const HomePage(), }, ); } }
ログイン・ログアウト処理を実装する
Login画面とHome画面にあるボタンの実装をしていきます。
ログイン・ログアウトを処理を行うクラスを追加する
class AuthenticationProvider { static bool isSignedIn() { return FirebaseAuth.instance.currentUser != null; } static Future<User?> signIn() async { final FirebaseAuth auth = FirebaseAuth.instance; final GoogleAuthProvider authProvider = GoogleAuthProvider(); final UserCredential userCredential = await auth.signInWithPopup(authProvider); return userCredential.user; } static Future<void> signOut() async { final FirebaseAuth auth = FirebaseAuth.instance; await auth.signOut(); } }
ログインボタンのonPressedを書き換えて、ログインできるようにする
onPressed: () { showDialog( context: context, builder: (_) => const Center(child: CircularProgressIndicator()), ); AuthenticationProvider.signIn().then((user) { Navigator.of(context).pop(); if (user == null) throw Exception('User is null'); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Welcome ${user!.displayName}'), ), ); Navigator.of(context).pushReplacementNamed(HomePage.routeName()); }).catchError((error) { Navigator.of(context).pop(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(error.toString()), ), ); }); },
ログアウトボタンのonPressedを書き換えて、ログアウトできるようにする
onPressed: () { showDialog( context: context, builder: (_) => const Center(child: CircularProgressIndicator()), ); AuthenticationProvider.signOut().then((_) { Navigator.of(context).pop(); Navigator.of(context).pushReplacementNamed(LoginPage.routeName()); }).catchError((error) { Navigator.of(context).pop(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(error.toString()), ), ); }); },
アプリを起動してLogin画面とHome画面をログインの状態によって切り替えれることを確認する
アプリ起動時にログイン状態によって表示する画面を切り替える
ログインしたままの状態で画面を開き直すと、常にLogin画面が表示されている状態です。
そのため、ログイン済みであればHome画面を表示するように書き換えます。
initialRoute
で分岐させて初期表示の画面を切り替えるclass MyApp extends StatelessWidget { const MyApp({super.key}); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Authentication Demo', debugShowCheckedModeBanner: false, theme: ThemeData.dark(), // isSignedIn()の状態で初期表示の画面を切り替える initialRoute: AuthenticationProvider.isSignedIn() ? HomePage.routeName() : LoginPage.routeName(), routes: { LoginPage.routeName(): (context) => const LoginPage(), HomePage.routeName(): (context) => const HomePage(), }, ); } }
おわりに
以上が、FlutterとFirebaseを使用してGoogle認証を導入するための手順となります。
各手順の詳しい説明は、上記の章を参照してください。実際に手順に従って、アプリを作成してみてください。