FlutterアプリにGoogle認証を組み込む

#はじめに
Flutterを使ったモバイルアプリにGoogleでログインさせて使わせるという機能を作っていきたいと思います。色々なユーザー認証がありますが、Googleの認証を組み込むメリットは、そのGoogleユーザーの権限でGoogleのサービスが簡単に呼び出せるという点です。例えば、認証したGoogleのユーザーのGoogle PhotosにAPIでアクセスして、Google Photosを活用したモバイルアプリを作るといったこともできます。また、Androidユーザーであれば必ずGoogle IDを使っているのでユーザーIDを別途作ったりといったことが必要ありません。Androidを持っていないユーザーでもgmailを使うためにGoogle IDを持っている人は多くいると思います。ユーザーにIDを作成させるという手間をかけさせたくないが、認証はしたいという場合には最も敷居の低い構成ではないかと思います。

#前提
Googleの認証をFlutterに組み込む場合、[google_sign_in](https://pub.dev/packages/google_sign_in)プラグインを利用するのが簡単です。これを利用して進めます。

#Firebaseの設定とFlutterプロジェクトへの組み込み
Googleの認証連携をするためには、[Firebase](https://firebase.google.com/)を利用します。

まず、以下の通り、Firebaseでプロジェクトを作成します。
![Firebase_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/dad2199f-59b5-5dff-62ca-75a89b504d59.jpeg)

任意のプロジェクト名を入力します。
![Firebase_02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/5b97f855-9335-9f2a-6d24-3042626bf49c.jpeg)

プロジェクトをGoogleアナリティクスで分析するか決めます。推奨されている通り分析するで設定します。
![Firebase_03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/a41003a3-9e80-d9a3-b21f-e33e41c002fc.jpeg)

どのアカウントのアナリティクスに紐づけるか聞かれます。基本はFirebaseにアクセスしているユーザーアカウントと同じものになるはずです。
![Firebase_04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/c9f65651-b269-2194-7642-ea9707e46f81.jpeg)

プロジェクト作成完了画面が表示されるので続行します。
![Firebase_05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/4703151a-e13b-edb2-e0fd-f9838214ee0b.jpeg)

プロジェクトが作製されたので、__Authentication__を選択しGoogleでのログインができるように設定を開始します。
![Firebase_06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/196b2148-43c9-1e5a-4816-b0ae14c70f34.jpeg)

__Sign-in method__を表示するとGoogleが無効になっているので有効に設定する作業を実施します。
![Firebase_07.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/0b9f0d0a-97af-0999-89cf-749ad08e0806.jpeg)

有効にする設定を行うと、``プロジェクトの公開名``と``プロジェクトのサポートメール``の設定が要求されます。公開名は後ほどAndroidアプリの画面に表示されるので適切な名前を入力してください。サポートメールはFirebaseにアクセスしているユーザーアカウントと同じものになるはずです。
![Firebase_08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/916c3902-9f0a-d41c-4863-29aedbdfd76d.jpeg)

ここまで設定が終わったら次に``プロジェクトの設定``へ移動します。
![Firebase_09.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/86718b6c-f86c-16a9-916d-b4f0d508e20b.jpeg)

Androidアプリ用の設定を追加していきます。
![Firebase_10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/efbc8bfc-baf5-84c0-bfa5-e4a9497a5c95.jpeg)

Androidアプリの``パッケージ名``と``デバッグ用の署名証明書 SHA-1``にハッシュを設定します。
![Firebase_11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/26fd5331-7f00-119a-d561-b2e103462f3b.jpeg)

``パッケージ名``には、Flutterアプリのプロジェクトの、``<プロジェクトフォルダ>\Android\app\src\main``配下に__AndroidManifest.xml__が入っていますので、そのファイルの__package__に設定されているものを入力します。
`デバッグ用の署名証明書 SHA-1``には、[ここ](https://developers.google.com/android/guides/client-auth?authuser=1)の情報を参考にして作成するモバイルアプリのSHA-1フィンガープリントを取得して設定します。Flutterのプロジェクトの場合は、``<プロジェクトフォルダ>\Android``配下に__gradrew__が入っていますので、それを以下のように実行するのが簡単でしょう。

``` Console
./gradlew signingReport
```

処理結果が色々表示されますが、``SHA1:``で表示されるハッシュ値を利用します。

``` Console
SHA1: A7:46:・・・
```

次に、Firebaseの設定をFlutterプロジェクトに組み込みます。まず、google-services.jsonファイルをダウンロードし、``<プロジェクトフォルダ>\android\app\``ふるだの下に保存します。
![Firebase_12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/d6dfe627-0b1b-a349-7cbc-e8abd2f41d2a.jpeg)

次いで、画面の指示に従いプロジェクトレベルのbuild.gradleファイルに設定を追加していきます。
![Firebase_13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/2cfe0181-f5f0-84de-f910-a22dc317d5bd.jpeg)

Flutterプロジェクトの場合``<プロジェクトフォルダ>\android\build.gradle``ファイルに設定を行います。以下、実際に設定を追加したファイルの抜粋です。

``` gradle
buildscript {
    ext.kotlin_version = '1.3.50'
    repositories {
        google()
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'com.google.gms:google-services:4.3.4'
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}
…
```

次に、アプリレベルのbuild.gradleに設定を追加します。
![Firebase_14.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/a4f69173-c6ab-39be-eb2c-f47e2423aaeb.jpeg)


なお、今回は、Firebase Android BoMの設定はしていません。Flutterプロジェクトの場合``<プロジェクトフォルダ>\android\app\build.gradle``ファイルに設定を行います。以下、実際に設定を追加したファイルの抜粋です。

``` gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
apply plugin: 'com.google.gms.google-services'

```

以上で設定は完了です。
![Firebase_15.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/03965bca-74e3-2b0e-5b5e-2ac144dc4060.jpeg)


#Flutterアプリへの認証の実装

Flutterプロジェクトの``<プロジェクトフォルダ>\pubspec.yaml``に以下を記載します。

``` yaml
dependencies:
  google_sign_in: ^4.5.9
```

あとは、[サンプル](https://pub.dev/packages/google_sign_in/example)を見ながら実装していってください。
ポイントをいくつか記載します。

まず、__GoogleSignIn__のインスタンスを作ります。以下は、OpenID Connectに対応し、Google PhotosのAPIが叩けるようなと認証情報を要求するためのインスタンスになります。


``` dart
  var _googleSignIn = GoogleSignIn(
    scopes: <String>[
      'email',
      'openid',
      'profile',
      'https://www.googleapis.com/auth/photoslibrary',
    ],
  ); 
```

初期化処理では、認証しているユーザーが変化したら処理を行うようなハンドラを書いておきます。以下は、認証情報が変化した際に認証情報から、OpenId ConnectのIdTokenを取得する方法と、Google PhotosのAPIを呼び出すときに必要なAuthorizationヘッダの情報を取得している例である。前者をつかって他サービスと連携、後者を使ってGoogleのサービスを呼び出しと色々なことができるようになります。

``` dart
_googleSignIn.onCurrentUserChanged
        .listen((GoogleSignInAccount account) async {
      debugPrint(account.toString());
      String _idToken = await account.authentication.then((auth) {
        return auth.idToken;
      });
      List idTokenSplited = _idToken.split('.');
      debugPrint(idTokenSplited[0]);
      debugPrint(idTokenSplited[1]);
      debugPrint(idTokenSplited[2]);

      debugPrint((await account.authHeaders).toString());
});

``` 

他には以下のようなメソッドを使い画面を構築していきます。

_googleSignIn.signInSilently() : 一度ログインしたら、次回以降の認証情報の入力をスキップするために最初に呼び出してみるべきAPIです。このAPIの呼び出しで認証できなかったらログイン画面を表示するようにします。上記呼び出しに失敗した場合に以下のようにログインボタンを表示するようにアプリを構成するのが良いです。
![flutter_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/1d7b5cd7-96d4-d55f-70df-486741666444.jpeg)

ログインボタンを押下したら、_googleSignIn.signIn()を呼ぶように実装します。APIを呼ぶと以下のような画面が表示されます。Android端末にログインしているユーザー情報が自動で表示されます。
![flutter_02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/47838036-4020-c1bb-fe5b-bdd946144a87.jpeg)
ユーザーを選択すると以下のような画面が表示されます。今回GoogleSignInのインスタンスを作る際にGoogle Photosを呼び出せるように要求しているのでその権限を付与するかの確認画面です。
![flutter_03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/3f0608eb-b47c-974f-8a67-8a3600d78e6d.jpeg)

__Allow__を選択するとさらに次の画面にすすみます。Firebaseで設定したプロジェクトに対してGoogle Photosにアクセスをしてもよいかの確認画面がでます。Allowを押下するとログイン完了です。
![flutter_04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/273926/a2c366aa-f0d1-547c-12d5-56b76e362545.jpeg)

# まとめ
以上、ざっくりとですがFlutterアプリでGoogleでログインする機能を組み込んでみました。なお、今回はAndroidアプリの設定方法で説明していますので、iOSでもできるようにする場合には、公式サイトを確認し設定してみてください。私はMacを持っていないのでiPhoneアプリが開発できないのです・・・。

最後に、本記事も含めて連載的に記事を書いていこうと思います。目次は[こちら](https://www.makotomi.com/flutter-google-firebase-aws/)です。