🔥

Firebase AuthenticationのOauthをCapacitor上で動かす方法を選ぶ

2022/04/21に公開

以下の記事で、Capacitor 上で OAuth を使う方法が書かれています。

https://zenn.dev/ubie/articles/firebase-auth-hack

Capacitorに組み込まれているのはスタンドアロンなWebViewなので、ここに書かれているようにOauthをしようとすると以下のような問題が起こります。

- Google などの認証プロバイダは WebView 内でのアクセスを弾く (参考)
- 認証プロバイダからのコールバックが端末のデフォルトブラウザで開かれてしまい、ネイティブアプリに戻ってこれない

その課題解決のために「それでもWebView上で認証を行いたい」というのもひとつなのですが、Capacitorプラグインを併用すれば「認証プロバイダアプリ(例:Facebookログインの場合はFacebookアプリ)が入っている場合はアプリで認証、そうでなければWebViewで認証」といった処理を行うことができます。

Sign in With Apple

https://github.com/capacitor-community/apple-sign-in を使うとSign in With AppleをWebでもiOS上でも行うことができます。これとFirebase Authenticationを組み合わせてみましょう。

以下のように行うことができます。

// 1. SignInWithAppleを行い、ログイントークンを取得
const appleLogin: SignInWithAppleResponse = await SignInWithApple.authorize().catch(() => undefined);

if (appleLogin === undefined) {
  throw 'ログインが行われませんでした';
}

// 2. Firebase AuthenticationのOAuthProviderにトークンをセットしてFirebaseで利用できる形式に
const provider = new OAuthProvider('apple.com');
const credential = provider.credential({
  idToken: appleLogin.response.identityToken,
});

if (type === 'new') {
  // 3. OAuthProviderを用いて、ユーザの作成
  const currentUser = await signInWithCredential(this.afAuth, credential)
} else {
  // (もしくは既存ユーザにログインを追加)
  const currentUser = await linkWithCredential(this.afAuth.currentUser, credential)
}

肝になるのは、Oauthのトークンを、Firebase Authenticationの OAuthProvider にセットすることで、これで「WebViewでリダイレクト」と同じ処理を実装することができます。

Facebook Login

https://github.com/capacitor-community/facebook-login を利用します。

// 1. Facebookログインを行い、ログイントークンを取得
const FACEBOOK_PERMISSIONS = ['email', 'public_profile'];
const event = await FacebookLogin.login({
  permissions: FACEBOOK_PERMISSIONS,
}).catch(() => undefined);

if (event === undefined) {
  throw 'ログインが行われませんでした';
}

// 2. Firebase AuthenticationのFacebookAuthProviderにトークンをセットしてFirebaseで利用できる形式に
const credential = FacebookAuthProvider.credential(event.accessToken.token);

if (type === 'new') {
// 3. OAuthProviderを用いて、ユーザの作成
const currentUser = await signInWithCredential(this.afAuth, credential)
} else {
  // (もしくは既存ユーザにログインを追加)
  const currentUser = await linkWithCredential(this.afAuth.currentUser, credential)
}

FacebookAuthProvidernew OAuthProvider('facebook.com') と同じものです。

  • FacebookAuthProvider
  • GithubAuthProvider
  • GoogleAuthProvider
  • TwitterAuthProvider

はFirebase Authenticationが予め用意しているのでこのようにSign in With Appleよりも容易に実装することができます。それ以外の流れはすべて一緒ですね。

Google Auth

https://github.com/CodetrixStudio/CapacitorGoogleAuth を利用します。ただ、私はプロダクトでGoogle Auth対応をしていないので多分こうだろうなーとコードを実行せずに書いています。

// 1. SignInWithAppleを行い、ログイントークンを取得
const googleUser = await GoogleAuth.signIn().catch(() => undefined);

if (googleUser === undefined) {
  throw 'ログインが行われませんでした';
}

// 2. Firebase AuthenticationのOAuthProviderにトークンをセットしてFirebaseで利用できる形式に
const credential = GoogleAuthProvider.credential(googleUser.authentication.idToken);

if (type === 'new') {
  // 3. OAuthProviderを用いて、ユーザの作成
  const currentUser = await signInWithCredential(this.afAuth, credential)
} else {
  // (もしくは既存ユーザにログインを追加)
  const currentUser = await linkWithCredential(this.afAuth.currentUser, credential)
}

まとめ

上記プラグインを使う方法は、プラグイン毎にネイティブで挙動させるためのそれぞれの設定があり、少し手間でもあります。しかし、Web版とネイティブアプリ版の挙動を同一コードで実現することができ、個人的にお気に入りの手法です。ちなみにこれはどちらかというとWebファーストでプラグインに最小限頼る方法ではありますが、がっつりプラグイン頼みで実装しようと思ったら、

https://github.com/robingenz/capacitor-firebase/blob/main/packages/authentication/README.md

を採用するという手もあります。どのように実装したいかをイメージしながら、方法を取捨選択してもらえればと思います。

それではまた。

Discussion