FlutterでFirebaseAuthentication[Google認証]を使う

はじめに

flutterプロジェクトにてFirebaseに関する設定ができている前提で話を進めます。まだ、Firebaseの設定や設定ファイルの配置等終わってない場合は、先にこちらの連続記事を参考に準備してください。

準備が終わっている方は早速やってみましょう。

FirebaseAuthentication、Google認証を有効にする

Firebaseの管理画面にて、Authenticationを有効にし、Google認証を有効にしてください。その際、プロジェクト名とメールアドレスを設定する必要がありますが、これは実際にユーザが認証する際に表示されるみたいです。

pubspec.yamlに追加

次はflutter側の編集です。pubspec.yamlを開いてパッケージを追加しましょう。

dependencies: 
  flutter: 
    sdk: flutter 
  firebase_core: 
  firebase_auth: 
  google_sign_in:

上記がFirebaseAuthentication利用時に必要な物です。VSCodeであれば保存すると自動でパッケージを取得してくれます。他の環境やうまくいかない人はターミナルでflutter pub getしてください。

[iOS]info.plistの編集

先にiOSに必要な作業を行います。info.plistを開き、下記内容を追加します。

<key>CFBundleURLTypes</key>
	<array>
    	<dict>
        	<key>CFBundleTypeRole</key>
        		<string>Editor</string>
        	<key>CFBundleURLSchemes</key>
        		<array>
            	<!-- Copied from GoogleService-Info.plist key REVERSED_CLIENT_ID -->
            	<string>ここにコピペする。</string>
        	</array>
   	 	</dict>
	</array>

GoogleService-Info.plistに書いてある、「REVERSED_CLIENT_ID」の値をコピペしてください。そのまま保存。

[Android]デバッグ用SHA1取得

Android側は既に紹介してあるFirebaseAnalyticsで必要な設定が正しくできておりかつ、デバッグ環境と本番アプリのそれぞれでSHA1の値をFirebase側に設定する必要があります。今回は開発用SHA1を取得する手順のみ紹介します。本番用SHA1はGoogleConsoleから取得する?みたいです。

早速ですが、コマンドを入力してみましょう。

keytool -v -list -keystore ~/.android/debug.keystore

パスワードは何も入力せずEnterで大丈夫です。
自分の環境ではJavaRuntimeがないと言われたので準備します。

詳しい情報をクリックすると公式ページに飛ぶので、JDK Download -> MacOS Installerと進み、インストーラをダウンロード&実行します。dmgをダブルクリックするとインストーラのpkgがあるので、それを実行してください。

SHA1の値がわかったら、Firebase側で設定しましょう。

Google認証画面を呼び出す動作を実装

まずはGoogle認証画面を実際に呼び出す大事な部分を実装します。dartクラスファイルを新規作成し、staticなメソッドを実装します。

import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';

class FirebaseAuthHelper {
  static Future<FirebaseUser> signIn() async {
    final GoogleSignIn _googleSignIn = GoogleSignIn();
    final FirebaseAuth _auth = FirebaseAuth.instance;
    GoogleSignInAccount googleCurrentUser = _googleSignIn.currentUser;
    try {
      if (googleCurrentUser == null)
        googleCurrentUser = await _googleSignIn.signInSilently();
      if (googleCurrentUser == null)
        googleCurrentUser = await _googleSignIn.signIn();
      if (googleCurrentUser == null) return null;

      GoogleSignInAuthentication googleAuth =
          await googleCurrentUser.authentication;
      final AuthCredential credential = GoogleAuthProvider.getCredential(
        accessToken: googleAuth.accessToken,
        idToken: googleAuth.idToken,
      );
      final FirebaseUser user =
          (await _auth.signInWithCredential(credential)).user;
      print("signed in " + user.displayName);

      return user;
    } catch (e) {
      print(e);
      return null;
    }
  }
}

名前とかは自分の分かりやすい様に変更してください。そしてこのstaticなメソッドを呼び出す側を記述します。ボタンWidgetと結果表示用ダイアログを表示するメソッドのみ抜き出しますので、各自でいい感じに実装してください。

RaisedButton(
            child: Text('Sign in Google'),
            onPressed: () {
              FirebaseAuthHelper.signIn()
                  .then((FirebaseUser user) => _showResultDialog(user))
                  .catchError((e) => print(e));
            },
          ),
  void _showResultDialog(FirebaseUser user) {
    if (user == null) {
      showDialog(
        context: context,
        builder: (_) {
          return AlertDialog(
            title: Text("ログイン失敗"),
          );
        },
      );
    } else {
      showDialog(
        context: context,
        builder: (_) {
          return AlertDialog(
            title: Text("ログイン成功"),
            content: Text(user.displayName),
          );
        },
      );
    }
  }

動作確認

では実際にデバッグしてみましょう。以下はiOSでのイメージです。

Contiueを押すと、

そしてログイン情報を正しく入力すると、ログイン成功と出てその下にアカウント名が出ているはずです。また、2回目からは既にログイン状態のため、認証画面は通らずにログイン成功ダイアログが表示されるはずです。

自分も見落としていましたが、Androidのみうまくいかない場合はSHA1の設定が正しいかもう一度確認してみてください。

ログイン状態の保持について

実はFirebaseのパッケージが管理してくれているので、このままアプリを再起動して試してみると分かりますが、ログイン状態は保持されたままです。非常に楽ですね。逆に言えばサインアウト機能を実装しないとログインしたままになってしまいます。

まとめ

既に前に書いた記事等でFirebaseの設定が正しく行われていれば、特に難しい事はなく実装できたはずです。この辺りの情報はネット上でもあまりまとまっていないので(analyticsと同じで需要がない?)今後も継続してまとめていければなと思います。