はじめに
アプリケーションでユーザーごとにデータを管理するには、認証機能が必要です。Firebase Authenticationを使うことで、Googleサインインやメール・パスワード認証など、複数の方法で簡単に認証機能を追加することができます。この記事では、Firebase Authenticationを使ってFlutterアプリに認証機能を追加する方法を、初心者向けに解説します。
Firebase Authenticationのセットアップ
Firebaseプロジェクトの作成
- Firebaseコンソール(https://console.firebase.google.com/)にアクセスし、新しいプロジェクトを作成します。
- プロジェクトを作成したら、Firebase Authenticationを有効化します。
- iOS アプリをプロジェクトに追加します。
プロジェクト内で「Add app」ボタンをクリックし、「iOS」を選択します。
アプリのバンドル ID(com.example.myapp
など)を入力して登録します。 GoogleService-Info.plist
をダウンロードします。
Firebase コンソールで iOS アプリの登録が完了すると、GoogleService-Info.plist
ファイルをダウンロードできます。GoogleService-Info.plist
を Flutter プロジェクトのios/Runner
フォルダに追加します。必ずxcode上から追加してください。
FlutterアプリへのFirebaseの追加
FlutterアプリにFirebaseを連携するために、次の手順を行います。
Firebase CLIをインストールしていない場合、ターミナルで以下のコマンドを実行してインストールします。
npm install -g firebase-tools
FirebaseプロジェクトとFlutterアプリをリンクさせるため、以下のコマンドを実行します。
firebase login
firebase init
firebase initの時の質問は一旦下記のように回答します。
? Which Firebase features do you want to set up for this directory? Press Space
to select features, then Enter to confirm your choices. Functions: Configure a
Cloud Functions directory and its files
? Please select an option: Use an existing project
? Select a default Firebase project for this directory: flutter-app
(Flutter-app)
? What language would you like to use to write Cloud Functions? TypeScript
? Do you want to use ESLint to catch probable bugs and enforce style? Yes
pubspec.yaml
に必要なパッケージを追加します。(バージョンは適宜変更してください)
dependencies:
firebase_core: ^3.6.0
firebase_auth: ^5.3.1
その後、以下のコマンドでパッケージをインストールします。
flutter pub get
Firebase Authenticationの実装
Firebaseの初期化
まず、Firebaseをアプリで使用できるように初期化します。main.dart
に以下のコードを追加して、アプリ起動時にFirebaseを初期化します。
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: AuthenticationWrapper(),
);
}
}
認証状態に応じた表示の切り替え
認証状態によって、ログイン画面かユーザーのTodoリスト画面を表示するようにします。以下のコードでは、認証状態に応じて画面を切り替える処理を実装しています。
class AuthenticationWrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasData) {
return MyHomePage(); // 認証されている場合
} else {
return LoginScreen(); // 未認証の場合
}
},
);
}
}
iosの設定
Podfileを編集し、下記コードを追加します。
platform :ios, '13.0'
メール・パスワード認証の実装
メールアドレスとパスワードを使用してサインアップ&サインインも簡単に実装できます。
class LoginScreen extends StatefulWidget {
@override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
Future<void> _signIn() async {
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: _emailController.text.trim(),
password: _passwordController.text.trim(),
);
} catch (e) {
print('ログインに失敗しました: $e');
}
}
Future<void> _signUp() async {
try {
await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: _emailController.text.trim(),
password: _passwordController.text.trim(),
);
} catch (e) {
print('サインアップに失敗しました: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('ログイン')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: _emailController,
decoration: InputDecoration(labelText: 'メールアドレス'),
),
TextField(
controller: _passwordController,
decoration: InputDecoration(labelText: 'パスワード'),
obscureText: true,
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _signIn,
child: Text('ログイン'),
),
ElevatedButton(
onPressed: _signUp,
child: Text('サインアップ'),
),
],
),
),
);
}
}
Googleサインインの導入
Googleサインイン導入方法についても解説していきます。
Firebase Authenticationの設定
Authenticationのログイン方法の設定画面にてGoogle認証を許可します。
google_sign_inパッケージの追加
Googleでサインインするには、google_sign_in
パッケージも追加します。
dependencies:
google_sign_in: ^5.4.0
URLスキームの追加
下記手順に従ってURLスキームの設定を行います。
- Xcodeでプロジェクトを開きます。
Runner
プロジェクトのターゲット設定(左側のプロジェクトナビゲータから選択)に移動します。- タブの中にあるInfoタブを開きます。
- URL Typesのセクションまでスクロールし、URL Schemesを追加します。
- ここに、GoogleService-Info.plist内を参考に値を入力します。
Identifer
:REVERSED_CLIENT_ID
URL_Schemes:com.googleusercontent.apps.xxxxxxx
のような形式のもの
- ここに、GoogleService-Info.plist内を参考に値を入力します。
Googleサインイン機能の実装
import 'package:google_sign_in/google_sign_in.dart';
Future<void> _signInWithGoogle() async {
try {
// Googleサインイン
final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
final GoogleSignInAuthentication googleAuth = await googleUser!.authentication;
// Firebase認証に必要なクレデンシャル
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
// サインインをFirebaseに登録
await FirebaseAuth.instance.signInWithCredential(credential);
} catch (e) {
print('Googleサインインに失敗しました: $e');
}
}
今回のコード
今回の完成系のコードです。
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Firebase Auth Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: AuthenticationWrapper(),
);
}
}
class AuthenticationWrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasData) {
return MyHomePage(); // 認証されている場合
} else {
return LoginScreen(); // 未認証の場合
}
},
);
}
}
// ホーム画面(ログイン後)
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('ホーム'),
actions: [
IconButton(
icon: Icon(Icons.logout),
onPressed: () async {
await FirebaseAuth.instance.signOut();
},
),
],
),
body: Center(
child: Text('ログイン済みです!'),
),
);
}
}
// ログイン画面
class LoginScreen extends StatefulWidget {
@override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
Future<void> _signIn() async {
try {
await FirebaseAuth.instance.signInWithEmailAndPassword(
email: _emailController.text.trim(),
password: _passwordController.text.trim(),
);
} catch (e) {
print('ログインに失敗しました: $e');
}
}
Future<void> _signUp() async {
try {
await FirebaseAuth.instance.createUserWithEmailAndPassword(
email: _emailController.text.trim(),
password: _passwordController.text.trim(),
);
} catch (e) {
print('サインアップに失敗しました: $e');
}
}
Future<void> _signInWithGoogle() async {
try {
// Googleサインイン
final GoogleSignInAccount? googleUser = await GoogleSignIn().signIn();
final GoogleSignInAuthentication googleAuth = await googleUser!.authentication;
// Firebase認証に必要なクレデンシャル
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
// サインインをFirebaseに登録
await FirebaseAuth.instance.signInWithCredential(credential);
} catch (e) {
print('Googleサインインに失敗しました: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('ログイン')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextField(
controller: _emailController,
decoration: InputDecoration(labelText: 'メールアドレス'),
),
TextField(
controller: _passwordController,
decoration: InputDecoration(labelText: 'パスワード'),
obscureText: true,
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _signIn,
child: Text('ログイン'),
),
ElevatedButton(
onPressed: _signUp,
child: Text('サインアップ'),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _signInWithGoogle, // Googleサインインボタン
child: Text('Googleでサインイン'),
),
],
),
),
);
}
}
Firebase Authenticationのメリット
Firebase Authenticationは、複数の認証方法を提供しており、Googleサインインやメール・パスワード認証だけでなく、AppleやFacebookなどの他のプロバイダーとの連携も可能です。
- セキュリティの向上:Firebaseが提供するセキュアな認証システムを利用できるため、セキュリティの心配が少なくなります。
- 簡単な実装:複雑なサーバーサイドのコードを書くことなく、簡単に認証機能をアプリに追加できます。
まとめ
この記事では、Firebase AuthenticationをFlutterアプリに導入する方法を紹介しました。
アプリ開発を行う上で認証機能はほぼほぼ必須だと思うので、別記事で認証機能や暗号化について学びたいと思います。
この記事のポイント
- Firebase Authenticationを使って、Googleサインインやメール・パスワード認証を導入。
- 認証状態に応じて、画面を切り替える
この記事が参考になったら幸いです。
コメント