22
20

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 Web x Firebase Auth x Google認証を実装してみる

Posted at

この記事は Flutter Advent Calendar 2019 16日目の記事です。

Flutter使ってみたいなーと思っていたので、まずはFirebase Auth + Google認証を組み込んだ上で、Flutter Webでの挙動を確認してみたよ。という内容になっています。主にWebでの挙動確認が主目的です。参考にしたサンプルの品質が若干怪しいので、それだけ気をつけてください。

Firebase Auth + Google認証の組み込み

Flutter Webは直近ベータになったようですが、まだ知見も少ないので、まずはモバイル(Android)でちゃんと動くかどうかを確認してから進めました。まずは下準備として、以下の記事あたりを参考に、Androidで認証フローを一通り確認できるようにしています。

認証部分のコードは以下のようになっています(記事からの引用)

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

final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();

Future<String> signInWithGoogle() async {
  final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
  final GoogleSignInAuthentication googleSignInAuthentication =
  await googleSignInAccount.authentication;

  final AuthCredential credential = GoogleAuthProvider.getCredential(
    accessToken: googleSignInAuthentication.accessToken,
    idToken: googleSignInAuthentication.idToken,
  );

  final AuthResult authResult = await FirebaseAuth.instance.signInWithCredential(credential);
  final FirebaseUser user = authResult.user;

  assert(!user.isAnonymous);
  assert(await user.getIdToken() != null);

  final FirebaseUser currentUser = await _auth.currentUser();
  assert(user.uid == currentUser.uid);

  return 'signInWithGoogle succeeded: $user';
}

void signOutGoogle() async{
  await googleSignIn.signOut();

  print("User Sign Out");
}

GoogleからIDトークン取得 → FirebaseへIDトークンを投げて認証 が大きな流れになっております。このサンプルではGoogleからトークンを取得するフローがImplicitっぽいのが気になりました。あとFirebase Authってリプレイアタックし放題なんですっけ。

...チョット本筋とズレてしまうので今回はこのまま進めます。

Flutter Web をビルドする準備

Webをビルドできるようにします。
ベータ版を有効にする必要があります。

flutter channel beta
flutter upgrade
flutter config --enable-web

flutter devicesを叩いて Chrome が確認できればOK

$ flutter devices

Android SDK built for x86 • emulator-5554 • android-x86    • Android 9 (API 28) (emulator)
Chrome                    • chrome        • web-javascript • Google Chrome 78.0.3904.108
Web Server                • web-server    • web-javascript • Flutter Tools

既存のプロジェクトにWeb版を追加する場合は以下コマンドでOKです。

flutter create .

実行すると、各種設定ファイルが生成されると思います。分かりやすいところだろ web/index.html ですね。

web/index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>flutter_auth_playground</title>
</head>
<body>
  <script src="main.dart.js" type="application/javascript"></script>
</body>
</html>

packages getしてパッケージを最新にしておきましょう。
次のコマンドWebを起動します。

flutter run -d chrome

動きました。やったね。

起動時のポートの固定方法

前述した起動方法だと、毎回ポートが変わります。
ポートが毎回変わるとOAuth 2.0のオリジン検証で弾かれるのが面倒なので、起動時のポートを固定しておくと捗ります。

flutter run -d chrome --web-port=3333

Android Studioの場合は下記から設定できます。

image.png

Google OAuth と Firebaseの接続設定

Androidだと android/app/google-services.json をぶっこむだけでしたが、Web版の場合はindex.htmlのヘッダに接続情報を記述します。また、firebaseのスクリプトを読ませる必要があります。

web/index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="google-signin-client_id" content="0123456789-xxxxxxxxxxxxxxxx.apps.googleusercontent.com" />
  <title>flutter_auth_playground</title>
</head>
<body>
  <script src="https://www.gstatic.com/firebasejs/7.5.0/firebase-app.js"></script>
  <script src="https://www.gstatic.com/firebasejs/7.5.0/firebase-auth.js"></script>
  <script src="main.dart.js" type="application/javascript"></script>
</body>
</html>

google-signin-client_id はGCPのOAuthクライアント作成で取得したクライアントIDを使います。
作成時に承認済みのURLに、先程ポートを固定したURIを設定しておきます。

次に、Firebase側でWeb用アプリを追加し、その際に発行されたfirebaseConfigを覚えておきます。

firebaseConfigを参考に、以下のような形でmain.dartに記述します。

main.dart
import 'package:firebase/firebase.dart' as firebase;

void main() {
  firebase.initializeApp(
    apiKey: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    authDomain: "xxxxxxxxxxx.firebaseapp.com",
    databaseURL: "https://xxxxxxxxxxx.firebaseio.com",
    projectId: "xxxxxxxxxxxx",
    storageBucket: "xxxxxxxxxxx.appspot.com"
  );

  runApp(MyApp());
}

設定はこれで終わりです。

動かしてみる

(Sign in with Google) をクリックしてGoogle認証を通すと...

動きました :tada:

気になっていたトークンの格納場所ですが、IndexedDBの中を掘っていったところのstsTokenManagerにアクセストークンもリフレッシュトークンも保存されていました。まあWeb Storageに入れるしかないよなーという感じですね。

token.png

まとめ

Flutter Web に Firebase AuthとGoogle認証を組み込んでみました。ほとんどコードを書き換えることなく各プラットフォームのビルドができるのは素晴らしい体験ですね。DOMではなくcanvasに描画されるので動きに若干の違和感はあるなーという感想でした。

明日はmirockさんがDesktop Embedding for Flutterについて書いてくれます!楽しみ!

22
20
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
22
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?