FlutterへFirebase AuthenticationとGoogle Sign-Inで簡単にログイン機能を実装

8 min read読了の目安(約7800字

はじめに

認証機能を一から作るのは大変です。
また、セキュリティに自信がないなら、自前で作らないほうが良いかと思います。(インターネットに公開したものは、容赦無く攻撃にさらされるので)

Firebase Authenticationは、Firebaseが提供する機能の一つです。
メール・パスワードによる認証だけでなく、GoogleやFacebookと連携した認証を提供してくれます。

Firebase Authenticationを使うと、簡単かつ安全にログイン機能を作りやすいです。
この記事では、Firebase Authenticationと、Googleアカウントを使った、Flutterでのログイン機能の作り方を解説します。

事前準備(Firebase Authentication)

今回はGoogleアカウントを使ったサインインを実装します。

サインイン方法を使用する前に、Firebase コンソールでサインイン方法を設定しておく必要があります。。

まず、Firebase>Authenticationへアクセスし、「ログイン方法を設定」ボタンを押します。
firebase-auth-login-setting

Googleアカウントでログインするためには、Google>有効にする、をオンにします。

enabled-google-sign-in
プロジェクト公開名は、サービスにログインした際のGoogleからのセキュリティ通知(「お使いの Google アカウントへのアクセスが <プロジェクト参照名> に許可されました」)などで使われる、ユーザに公開されるプロジェクトの名前です。

プロジェクトのサポートメール、にもメールアドレスを設定し、保存を押します。

あとは、Googleのステータスを確認し、有効になっていればOKです。

confirm-google-sign-in-enabled

事前準備(Flutter)

今回の実装では次のパッケージを使います。

dependencies:
  flutter:
    sdk: flutter
  firebase_core: ^0.4.2+1
  firebase_auth: ^0.15.1
  google_sign_in: ^4.0.14
  flutter_signin_button: ^1.1.0

pubspec.yamlにこれらを追記たら、flutter pub getでインストールしておきます。

また、今回はGoogle Sign-in部分について設定しておく必要があります。
google_sign_in | Flutter Package

公式サイトに従い、Info.plistにCFBundleTypeRoleと、CFBundleURLSchemesを追加します。

CFBundleURLSchemesは、array>string部分にGoogleService-Info.plistの、REVERSED_CLIENT_IDキーをコピーして貼り付けます。

<key>CFBundleURLTypes</key>
<array>
	<dict>
		<key>CFBundleTypeRole</key>
		<string>Editor</string>
		<key>CFBundleURLSchemes</key>
		<array>
			<!-- TODO  GoogleService-Info.plistからREVERSED_CLIENT_IDキーをコピーして、
      ここの値を置き換える -->
			<string>com.googleusercontent.apps.861823949799-xxxxxxxxxxxxxxxxxxxxxxxxx</string>
		</array>
	</dict>
</array>

なお、ここで設定(書き方など)をミスっていると、google_sign_inプラグインを使う際、次のエラーが出て、アプリがクラッシュします。

Failed to send request: {"jsonrpc":"2.0","id":"100","method":"getStack","params":{"isolateId":"isolates/392598366557863"}}
Failed to send request: {"jsonrpc":"2.0","id":"101","method":"getObject","params":{"isolateId":"isolates/392598366557863","objectId":"classes/3284"}}
Failed to send request: {"jsonrpc":"2.0","id":"102","method":"invoke","params":{"isolateId":"isolates/392598366557863","targetId":"objects/629","selector":"toString","argumentIds":[],"disableBreakpoints":true}}

詳細なログを見ると、URL schemes部分でエラーが発生しています。

$ flutter run -verbose
...
...
[+26526 ms] flutter: Exception
[        ] flutter: PlatformException(google_sign_in, Your app is missing support for the following URL schemes: com.googleusercontent.apps.480616290440-xxxxxxxxxxxxxxxxxxxxxxxx, NSInvalidArgumentException, null)
[  +17 ms] Service protocol connection closed.
[        ] Lost connection to device.
[   +3 ms] DevFS: Deleting filesystem on the device (hogehoge)
[ +257 ms] Ignored error while cleaning up DevFS: TimeoutException after 0:00:00.250000: Future not completed
[   +1 ms] "flutter run" took 134,429ms.
[   +2 ms] ensureAnalyticsSent: 0ms
[        ] Running shutdown hooks
[        ] Shutdown hook priority 4
[   +1 ms] Shutdown hooks complete
[        ] exiting with code 0

Xcodeで、TARGETS>Info>URL Typesを確認して、何も値が表示されていなければ、設定をミスっているので、Xcode上でも良いので正しく設定しておきます。
(設定方法 : IOS : Login google Crash : ‘Your app is missing support for the following URL schemes: com.googleusercontent.app’ | by TungShien.com | CodeSpace69 | Medium )

xcode-url-schemes

実装(Flutter)

では、事前準備を終えたら、実装を進めます。
まず、main関数をasync関数にし、Fireabseを初期化します。

Future<void> main() async {
  // この2行を加える
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  runApp(SignInDemoApp());
}

また、次のようなウィジェットを用意します。

class SignInDemo extends StatefulWidget {
  
  State createState() => SignInDemoState();
}

class SignInDemoState extends State<SignInDemo> {
  final _auth = FirebaseAuth.instance;
  
  Widget build(BuildContext context) {
    return Scaffold();
  }
}

私はこの辺りで、次のようなエラー出て、ビルドに失敗しました。

Error: CocoaPods's specs repository is too out-of-date to satisfy dependencies.
To update the CocoaPods specs, run:
  pod repo update

Error running pod install
Error launching application on iPad Pro (12.9-inch) (4th generation).
[!] CocoaPods could not find compatible versions for pod "Firebase/CoreOnly":
  In snapshot (Podfile.lock):
    Firebase/CoreOnly (= 6.26.0, ~> 6.26.0)

  In Podfile:
    cloud_firestore (from `.symlinks/plugins/cloud_firestore/ios`) was resolved to 0.14.1-3, which depends on
      Firebase/CoreOnly (~> 6.33.0)


You have either:
 * changed the constraints of dependency `Firebase/CoreOnly` inside your development pod `cloud_firestore`.
   You should run `pod update Firebase/CoreOnly` to apply changes you've made.

CocoaPodsが依存関係の解決に失敗しているようですが、エラー画面で支持された対処方法( pod repo update 等)を試しても解決せず。

次の方法で解決することができました。

cd <Flutterプロジェクト>
cd ios
rm Podfile.lock
pod install --repo-update
cd ..
flutter clean

次に、Googleアカウントを使った、ログイン部分を実装します。

サインインボタンから、次のsignInWithGoogle()を呼び出すことで、ログインすることができます。

  // Googleを使ってサインイン
  Future<UserCredential> signInWithGoogle() async {
    // 認証フローのトリガー
    final googleUser = await GoogleSignIn(scopes: [
      'email',
    ]).signIn();
    // リクエストから、認証情報を取得
    final googleAuth = await googleUser.authentication;
    // クレデンシャルを新しく作成
    final credential = GoogleAuthProvider.credential(
      accessToken: googleAuth.accessToken,
      idToken: googleAuth.idToken,
    );
    // サインインしたら、UserCredentialを返す
    return FirebaseAuth.instance.signInWithCredential(credential);
  }

signInWithGoogle()を呼び出す側はこんな感じです。

onPressed: () async {
        try {
          final userCredential = await signInWithGoogle();
        } on FirebaseAuthException catch (e) {
          print('FirebaseAuthException');
          print('${e.code}');
        } on Exception catch (e) {
          print('Other Exception');
          print('${e.toString()}');
        }
}

あとはアプリをビルドすると、ログインすることができます。
なお、全コードは次へ置いておきます。

FirebaseAuthentication demo using Google Sign-in in Flutter.

結果

まず、こういう画面が出るので、「Sign in with Google」をクリックし、ログインを進めていきます。

auth-home

ログインを進めていくと、現時点では次のような画面が出ますが、詳細を表示>(安全でないページ)に移動をクリックします。
confirm-app-auth

あとは、流れ通り確認を進めると、ログインすることができます。

参考文献

Authentication | FlutterFire
Social Authentication | FlutterFire
The OAuth 2.0 Authorization Framework
OAuth 2.0 Scopes for Google APIs | Google Identity Platform
[google_sign_in] Google sign in crashes the flutter app in IOS device · Issue #44564 · flutter/flutter
IOS : Login google Crash : ‘Your app is missing support for the following URL schemes: com.googleusercontent.app’ | by TungShien.com | CodeSpace69 | Medium
ちょっとでもセキュリティに自信がないなら、 Firebase Authentication を検討しよう - mizdev