1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Flutter×FirebaseのGoogle認証(2021年4月版)

Posted at

:book: Flutterの記事を整理し本にしました :book:

  • 本稿の記事を含む様々な記事を体系的に整理し本にまとめました
  • 今後はこちらを最新化するため、最新情報はこちらをご確認くださ
  • 10万文字を超える超大作になっています(笑)

はじめに

  • FlutterのFirebaseパッケージのメソッドとかがコロコロ変わる印象があり、先人方のコピペで動かない事があったので、最新版で動くものを整理しました。

まとめ

概要

FirebaseのAuthenticationの基本については、Firebaseの機能1-1:Authentication(メール)をご参照ください。

Firebase Authentication(以下Authentication)には、メールとパスワード以外にも、様々なSNSとの連携が実現できるようになっています。

本チャプターでは、一番代表的なGoogleアカウントとの連携の実装を解説します。

この認証方法を使えば、メールアドレスを登録することなく、Googleアカウントさえ持っていれば、認証を通ることができます。

開発者側は、ユーザのUIDがメールでもGoogle認証でも同じように払い出されますので、認証後は統一したロジックで処理を行うことができます。

事前準備

共通の設定

まずは、FirebaseでGoogleAuthを有効化します。

pic3.png

Authenticationから、プロバイダーのGoogleを有効にします。
プロジェクトの公開名はデフォルトでも構いませんが、認証時にユーザに表示されます。

Androidの設定

AndroidではSHA1のフィンガープリントが必要になります。

keygen.sh
% keytool -list -v-alias androiddebugkey -keystore ~/.android/debug.keystore
キーストアのパスワードを入力してください:  
別名: androiddebugkey
作成日: 2020/08/09
エントリ・タイプ: PrivateKeyEntry
証明書チェーンの長さ: 1
証明書[1]:
所有者: C=US, O=Android, CN=Android Debug
発行者: C=US, O=Android, CN=Android Debug
シリアル番号: 1
有効期間の開始日: Sun Aug 09 19:24:48 PWT 2020終了日: Tue Aug 02 19:24:48 PWT 2050
証明書のフィンガプリント:
	 MD5: ********
	 SHA1: ********
	 SHA256: ********
	 署名アルゴリズム名: SHA1withRSA
	 バージョン: 1

まず、コマンドでSHA1のフィンガプリントを作成し、下記のアプリの設定部分に登録します。
パスワードは特にありませんので、そのままEnterを入れてください。

pic4.png

続いて、SHA1を設定した後は、再度google-services.jsonをダウンロードし配置します。

google-services.jsonの設定方法については、Firebase概要をご確認ください。

iOSの設定

info.plist
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>{REVERSED_CLIENT_ID}</string>
        </array>
    </dict>
</array>

info.plistに設定を追加します。
下記イメージの通り、CFBundleURLSchemesにREVERSED_CLIENT_IDを設定します。

pic5.png

実装

ここ数年でメソッド名が変わったりしていますので、ご注意ください。
(FirebaseUserがUserに変更されたり、getCredentialがcredentialに変更されたりしています
本チャプターは下記のパッケージバージョンで動作確認をしています。

まず、必要なパッケージをインストールします。
必要に応じて、最新のバージョンをお使いください。

pubspec.yaml
dependencies:
  firebase_core: ^1.0.4
  firebase_auth: ^1.1.1
  google_sign_in: ^5.0.2

続いて、検証に用いる画面のソースコードになります。
ログインのページとログアウトのページを準備し、それぞれの動作を確認していきます。

main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:firebase_test/LoginPage.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: LoginPage(),
    );
  }
}

メイン画面は、LoginPageを呼び出すだけですが、Firebaseを初期化するために、main関数を非同期にした上で、初期化用のメソッドを呼んでいます。

LoginPage.dart
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:firebase_test/LogoutPage.dart';

class LoginPage extends StatelessWidget {
  static final googleLogin = GoogleSignIn(scopes: [
    'email',
    'https://www.googleapis.com/auth/contacts.readonly',
  ]);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Demo'),
      ),
      body: Center(
        child: TextButton(
          onPressed: () async {
            GoogleSignInAccount signinAccount = await googleLogin.signIn();
            if (signinAccount == null) return;
            GoogleSignInAuthentication auth =
                await signinAccount.authentication;
            final GoogleAuthCredential credential =
                GoogleAuthProvider.credential(
              idToken: auth.idToken,
              accessToken: auth.accessToken,
            );
            User user =
                (await FirebaseAuth.instance.signInWithCredential(credential))
                    .user;
            if (user != null) {
              await Navigator.of(context).pushReplacement(
                MaterialPageRoute(builder: (context) {
                  return LogoutPage(user);
                }),
              );
            }
          },
          child: Text(
            'login',
            style: TextStyle(fontSize: 50),
          ),
        ),
      ),
    );
  }
}

続いて、ログイン画面です。
画面には、ボタンが1つあるだけで、ログインボタンを押すと認証を行います。
処理は、GoogleSignInでアカウントを取得したあとに、GoogleSignInAuthentication,GoogleAuthCredentialで認証を行います。

Google認証が問題なく行われたあとに、この情報を使って、Firebaseに認証情報を登録します。
該当部分は、FirebaseAuth.instance.signInWithCredential(credential))になります。

返ってきたユーザ情報を持って、ログアウトページに遷移しています。

Logout.dart
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:firebase_test/LoginPage.dart';

class LogoutPage extends StatelessWidget {
  User user;
  LogoutPage(this.user);
  static final googleLogin = GoogleSignIn(scopes: [
    'email',
    'https://www.googleapis.com/auth/contacts.readonly',
  ]);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text("Hello ${user.displayName}", style: TextStyle(fontSize: 50)),
            SizedBox(height: 20),
            TextButton(
              onPressed: () async {
                FirebaseAuth.instance.signOut();
                await googleLogin.signIn();
                await Navigator.of(context)
                    .pushReplacement(MaterialPageRoute(builder: (context) {
                  return LoginPage();
                }));
              },
              child: Text('Logout', style: TextStyle(fontSize: 50)),
            )
          ],
        ),
      ),
    );
  }
}

最後は、ログアウト画面です。
ログアウト画面は、認証されたuserdisplayNameを使ってユーザ名を表示しています。
その下にログアウトのボタンを配置し、ボタンを押すとログアウトが行われます。

処理は、まずFirebaseAuth.instance.signOut();でFirebaseのログアウトを行います。
次にgoogleLogin.signIn();でGoogleのログアウトを行います。
最後に、ログインページに遷移しています。

動作イメージ

実際の動作イメージは下記のようになります。

pic1.png

初回のみ設定が必要となりますが、2回目からは問い合わせのみになるため、スムーズなログイン/ログアウトが行えます。

AndroidとiPhoneで表示される内容やステップが若干異なります。
また、2要素認証の有無によっても初回の動作が異なります。

Firebase側にもプロバイダーがGoogleの認証情報が登録されています。
pic2.png

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?