FlutterとFirebaseとFacebookと、クロスプラットフォームログインのはなし

この記事はJX通信社 Advent Calendar 2019 6日目の記事です。

Flutter に Firebase Authentication と Facebook認証を組み合わせる話

こんにちは、Flutter(Andorid)エンジニアのぬまっちです。(@nuMatch)
先月は登壇してきましたブログ

tech.jxpress.net

を投稿しました。

記事の最後に予告した通り、今回はFlutter と Firebaseの相性の良さについて筆を走らせたいと思います。

特にFirebase AuthenticationFacebook認証が今回の主役になります。

おしながき

  • ログイン機構と3つのF
  • Firebase Authentication の仕組みについて
  • Flutter側での実装

ログイン機構と3つのF

初めに、この記事は

Flutterでクロスプラットフォームアプリを構築したエンジニアが、
少ない労力でユーザーログイン機能を実装できる世界

を目指して、 FlutterアプリにFirebase Authentication (以下、Firebase Auth)を実装し、 Facebookアカウントを用いたログイン機能を実現させることを目的としています。

彼らをまとめて3つのFと呼称したいと思います。

アプリを作る上でユーザーを識別したい、という場面は想像に難くありません。
それくらいにアカウント管理という機能は私達に密接ですが、いざ組み込もうと思うと考慮しなければいけない事は無数にあります。

当然、セキュリティ対策は考えなければなりませんし、ユーザーにとってもログインのし易い作りになっている事も重要です。

Flutterを選択して効率の良いクロスプラットフォームアプリを構築された方にはぜひ、Firebase Authを組み合わせて欲しいです。

Firebase Authentication の仕組みについて

Firebase Authとはメールアドレスとパスワードによる管理のほか、 FacebookやTwitterといった複数のプロバイダOAuth トークンによるログイン認証に対応したBaaSのことです。

世の中にはすでに各プロバイダから Facebook OAuthや Twitter OAuthを使ったログイン機能が溢れていますが、
Firebase Authを組み合わせる事によって、ダッシュボード上での複数プロバイダの管理を行うことが出来るようになります。

f:id:numatch-jx:20191206115157p:plain:w500

上記のダッシュボードでは、Firebase Authが管理出来るログインプロバイダ覧が見て取れると思います。 また、この画面から各プロバイダの有効/無効の管理をする事も出来ます。

つまりメールアドレス&パスワードによるログインユーザーと、各プロバイダのログインユーザーを紐付けて
Firebase Auth上では一人のアカウントとして管理する事が出来るという事なのです。

f:id:numatch-jx:20191206170421p:plain

Cloud FirestoreのようなFirebaseが提供するオンラインデータベースサービスも、
Firebase Auth上のアカウント単位でユーザーを管理する事出来ます。

Facebook認証の準備

今回はフェデレーションIDプロバイダ*1としてFacebookを選択しています。 他のプロバイダよりも実名で登録されている事が多いので、そういった理由でプロバイダを選択するのもいいかもしれません。

今回、詳細は割愛させて頂きますがFacebook認証をアプリに実装するまでの簡単な流れを説明します。

  1. Facebook Developer上でアプリIDを申請する

下記サイトから申請することが出来ます。(要 Facebook開発者アカウント) developers.facebook.com

iOS、またはAndroidのページから新規のアプリIDを申請しますが、Facebook Developer上のアプリIDは一つのものとして管理されます。

2.開発環境を設定する

Flutterアプリとして iOS / Android のクロスプラットフォームに対応するなら、両OS用に設定が必要になります。 それぞれ日本語ドキュメントでしっかり説明しているので、順番に対応しましょう。

  • iOS

iOS - Facebookログイン - ドキュメンテーション - Facebook for Developers

Flutter上に実装するなら 4.プロジェクトを構成する まで準備すれば問題ないと思います。

  • Android

Android - Facebookログイン - ドキュメンテーション - Facebook for Developers

こちらも全部やる必要はありません。 7. アプリのシングルサインオンを有効にする まで準備しましょう。

注意する点としては

  • iOS : バンドルID
  • Android : パッケージ名,Default Activity のクラス名

を記入する必要があります。Flutterアプリ側で確認して間違えの無いように設定しましょう。

  1. Firebase Auth とFacebook 認証側を紐付ける

Facebook開発者画面で先ほど設定したアプリの設定画面に入るとアプリID , app secret を確認する事が出来ると思います。

f:id:numatch-jx:20191206120415p:plain

次に、Firebase Auth のダッシュボードでログインプロバイダの中からFacebookを選んで有効にして下さい。

するとアプリID , アプリ シークレット を入力する項目があるので、それぞれFacebookアプリ側のものを入力しましょう。

f:id:numatch-jx:20191206120606p:plain

また、Firebase Auth側には OAuth リダイレクト URI が表示されるので、
Facebookアプリ側の クライアントOAuth設定画面有効なOAuthリダイレクトURI に貼って上げましょう。

f:id:numatch-jx:20191206120819p:plain

これでFacebook認証の準備は完了です。

Flutter 側の実装

いよいよFlutterアプリ側への実装です。

大まかには

  1. Facebook認証を行ってOAuth トークンを取得する
  2. OAuth トークンをFirebase Auth側に渡す
  3. Firebase Auth 側で認証情報を検証してクライアント(Flutterアプリ)にレスポンスを返却する

という流れになります。

まず、Firebase Auth用とFacebook認証のFlutterプラグインを実装しましょう。

【pubspec.yaml】

dependencies:
  flutter:
    sdk: flutter

  firebase_auth: ^0.15.1
  firebase_core: 0.4.2+1
  flutter_facebook_login: ^3.0.0

(各プラグインのVersionは執筆時点のものです。Dart packages にて最新Versionをご確認ください。)

【dart】
  var facebookLogin = FacebookLogin();
  var permissions = ["email"]; // ユーザーがFacebookに登録してるメールアドレスを要求している。複数要求できる。
  var facebookLoginResult = await facebookLogin.logIn(permissions); // ログイン認証の結果が返却されている

上記の内容が実行されると、アプリ上でFacebookに遷移してログイン認証が行われます。 リダイレクト先の設定(Firebase Auth とFacebook認証の紐付け)が正常に出来ていれば、
Facebookにログイン後、Flutterアプリ側に戻ってくると思います。

【注意】
Facebook Login プラグイン*2のReadmeに紹介されている実装方法は古くなっています。 Version3.0.0以降で使うのなら上記の書き方にしてください。

↓Readmeでは下記の書き方のままになっている。

facebookLogin.logInWithReadPermissions(['email']);


facebookLoginResult.status でログインの状態を確認出来ます。

ログインステータスが、 FacebookLoginStatus.loggedIn で返却されているならログイン成功です!

次にFirebase Auth 側にユーザーアカウントを作成しましょう。

【dart】
/// FirebaseAuth インスタンスの取得
  final FirebaseAuth _auth = FirebaseAuth.instance;
  final FirebaseUser _user =  await _createFirebaseUesr(_auth, facebookLoginResult);

/// FirebaseAuth のインスタンスとFacebook認証トークンを使ってFirebase User を作成する
   Future<FirebaseUser> _createFirebaseUesr(
    FirebaseAuth _auth, FacebookLoginResult _result) async {
  var facebookAccessToken = await _result.accessToken;
  final AuthCredential credential = FacebookAuthProvider.getCredential( accessToken: facebookAccessToken.token);
  final AuthResult authResult = await _auth.signInWithCredential(credential);
  return authResult.user;
}

この

AuthResult.user

が取得出来ていればFirebase Authによるログイン認証は成功です!

Android iOS
f:id:numatch-jx:20191206163235g:plain f:id:numatch-jx:20191206163253g:plain

↑はサンプルアプリですがFirebase Authでのログインが成功して、Firestoreに接続出来ている状態です。

Firebase Auth のダッシュボードでユーザータブを確認すると、識別子にFacebookのメールアドレスが充てられたユーザーがいると思います。

また、ユーザーUIDがFirebase上で横断して使われるユニークIDになっており、 このIDで Cloud Firestore等の別サービスとの紐付けが行われます。

おわりに

今回はFlutter × Firebase Auth × Facebook認証 という3つのFを組み合わせた方法で、
アカウントを管理する手順を紹介しました。

限られたリソースでiOS、Androidのクロスプラットフォームを実現しつつユーザーアカウントも管理出来るようになる、一つの方法として有効なのではないでしょうか?

結婚式のスピーチではよく、「3つの袋」の話が使われますが、今度は代わりに3つのFをネタするのも良いじゃないかな?と思います!

*1:ログイン認証に使われるプロバイダ。Facebookの他にはTwitterが多く使われる。

*2:flutter_facebook_login | Flutter Package