FlutterWebでFirebaseのメールリンク認証を使う
修正リクは ➡️ |
---|
前回、FlutterでFirebaseのメールリンク認証を使うでiOSとAndroidでの方法を紹介しましたが、今回はfirebase_ui_authで現状サポートされていないFlutterWebでの方法の紹介です。
前回の続きを想定しているので基本的な設定は省略します。詳しくは前回の記事を参照してください。
これからやること
- WebはDynamicLinkをそのまま使えませんので、EmailLinkのリダイレクト先をサービスのログイン処理用のURLに設定します。
- 入力されたメールアドレスを一時的に保存します。
- 1のURLを処理できるように
go_router
等を設定します。 - URLを受け取った後のログイン処理を行います。
1. EmailLinkのリダイレクト先を設定する
前回の🎯Flutterの実装で設定したActionCodeSettings
のurlを変更します。
final origin = kDebugMode
? 'http://localhost:8081' // httpにしてください
: 'https://your-domain.com';
ActionCodeSettings(
- url: 'https://xxx.page.link',
+ url: '$origin/login/finish', // パスは自由です
dynamicLinkDomain: 'xxx.page.link',
handleCodeInApp: true,
// ...
);
一応デバッグ時はlocalhost
を使うようにしています。ポートは好きにしてください。
ただし、flutter run
する時、デフォルトではポートがランダムなので--web-port 8081
等で指定する必要があります。
2. 入力されたメールアドレスを一時的に保存する
- 保存には
shared_preferences
を使います。(shared_preferencesの使い方は本稿では省略します) - 入力されたメールアドレスを受け取る必要があります。
- 今回は簡単に
firebase_ui_auth
のEmailLinkSignInScreen
を弄って使います。 - 自分で実装するのももちろんありです。
- 今回は簡単に
私のGitHubリポジトリにある改造したfirebase_ui_auth
をインストールします。
(保守し続けていない可能性が高いので、その時はdiffを参照してご自身のフォークに反映して使ってください)
変更内容は
・webのサポートを追加
・EmailLinkSignInScreenにonLinkSent
コールバックを追加
の2点のみです。
pubspec.yaml
dependencies:
firebase_ui_auth:
git:
url: https://github.com/ywake/FirebaseUI-Flutter.git
path: packages/firebase_ui_auth
ref: email-link-web
dependency_overrides:
firebase_ui_auth:
git:
url: https://github.com/ywake/FirebaseUI-Flutter.git
path: packages/firebase_ui_auth
ref: email-link-web
これでEmailLinkSignInScreen
にonLinkSent
コールバックが追加されましたので、それを使ってメールアドレスを保存します。
class EmailLinkView extends StatelessWidget {
const EmailLinkView({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return EmailLinkSignInScreen(
onLinkSent: (email) {
sharedPreferences.setString('emailForSignIn', email);
},
);
}
}
3. URLを処理できるようにする
今回はgo_router
を使ってURLを処理できるようにします。(これも基本的な解説は省略します)
(ちなみにバージョンは13.x.x
を想定しています。APIの更新早いので変わっているかもしれません)
import 'package:go_router/go_router.dart';
GoRouter(
routes: [
// ...
GoRoute(
path: '/login/link',
pageBuilder: (context, state) => const EmailLinkView(),
),
+ GoRoute(
+ path: '/login/finish',
+ pageBuilder: (context, state) => FinishLogin(uri: state.uri),
+ ),
],
);
これから定義するFinishLogin
にUri
を渡しています。これがDynamicLinkから伝わる情報になります。
それとmain.dartに以下を追加します。
void main() {
+ setUrlStrategy(PathUrlStrategy());
runApp(MyApp());
}
これがないデフォルトではURLがyour-domain.com/#/path
といった形になってしまいカッコ悪いです。
もちろん#
があるままでもできますので、その場合はこれまでのコードを合わせてください。
4. ログイン処理を行う
ここまで設定すれば、送られてきたメールリンクをブラウザで開くとyour-domain.com/login/finish
に飛ぶはずですので、あとはそのページでログイン処理を行います。
概要を示すための適当なコードなので、適宜修正してください。
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class FinishLogin extends StatelessWidget {
const FinishLogin({Key? key, required this.uri}) : super(key: key);
final Uri uri;
Widget build(BuildContext context) {
if (FirebaseAuth.instance.isSignInWithEmailLink(uri.toString())) {
// ログイン処理
FirebaseAuth.instance.signInWithEmailLink(
email: sharedPreferences.getString('emailForSignIn')!,
emailLink: uri.toString(),
).then((_) {
// ログイン成功時の処理
sharedPreferences.remove('emailForSignIn');
}).catchError((e) {
// ログイン失敗時の処理
});
return Center(
child: CircularProgressIndicator(),
);
} else {
// 省略
}
}
}
go_routerから持ってきた「URL」と、SharedPreferencesに保存した「入力されたメールアドレス」をFirebaseAuth.instance.signInWithEmailLink()
に渡してログイン処理を行います。
5. 終わり🎉
お疲れ様でした!
いつかfirebase_ui_authでサポートされて簡単になることを願っています。
Discussion