くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

Firebase Authでカスタムトークン認証を試してみる

GoogleアカウントやTwitterなど以外でもFirebase Authを使いたいなと思い、
カスタムトークン認証を試してみるを試してみたときの備忘録

認証の流れ

全体の流れはこんな感じ。

  1. 外部の認証でUIDを取得する
  2. サーバ側: firebase-adminのcreateCustomToken()でカスタムトークンを作成する
  3. クライアント側: firebaseのsignInWithCustomToken()で認証する

カスタムトークンの作成にfirebase-adminが必要なので、サーバが必須なのが注意。
サーバじゃなくてCloud Functions上でもOK

1. 外部の認証でUIDを取得する

なにはともあれ、まずは外部の認証をする。

カスタムトークンを作成する際にUIDが必要なので、認証したユーザのIDを取得。

2. サーバ側: カスタムトークンの作成

UIDからFirebase Authcationの認証で使うカスタムトークンを作成する。

firebase-adminが必要なので、Cloud Functionsを使う。

// functions/src/index.ts

import * as functions from "firebase-functions";
import * as admin from "firebase-admin";

if (admin.apps.length < 1) {
  admin.initializeApp();
}

exports.auth = functions.https.onCall(async (data, context) => {
  // パラメタからUIDを取得
  const uid:string | null = data.uid || null;
  if (!uid) return null;

  // カスタムトークンの作成
  const customToken = await admin.auth().createCustomToken(uid);

  return customToken
});

3. クライアント側: カスタムトークンで認証する

最後に、クライアント側でカスタムトークンを使って認証する。
カスタムトークンの作成にCloud Functionsを使っているので、
Cloud FunctionsのhttpsCallableで呼び出す。

import firebase from "~/plugins/firebase"; // 初期設定済みのfirebase

export async function login(uid) {
  // Cloud Functionsを呼び出して、カスタムトークンを取得
  const authFunc = firebase.functions().httpsCallable("auth");
  const customToken = await authLogin({ uid: uid });

  // カスタムトークンで認証
  const credential = await firebase.auth().signInWithCustomToken(customToken);
}

これで外部の認証でのもFirebase Authが使えるように(´ω`)
Firebase Authで認証してるのでセキュリティルールとかでも対応できる(´ω`)

おまけ: Cloud Functionsでカスタムトークン作成権限を付与する

デフォルトの設定だと、Cloud Functionsのエージェントアカウントに権限がなくエラーが。。
iam.serviceAccounts.signBlobがないと言われてしまう。。

Cloud Functionsのサービスエージェントである
service-PROJECT_NUMBER@gcf-admin-robot.iam.gserviceaccount.com
権限がないよう。

なので、GCPのIAMの画面で権限を付与する。

デフォルトだと「Google提供のロール付与を含みます」にチェックがなく、
Cloud Functionsのサービスエージェントも表示されないので、チェックを入れる。

f:id:wannabe-jellyfish:20201201091618p:plain

iam.serviceAccounts.signBlobの権限を含むロールは、
「サービスアカウントトークン作成者」なので、変種ボタンからロールを追加する。

f:id:wannabe-jellyfish:20201201091639p:plain

これで、Cloud Functions上でカスタムトークンが作成できるように(´ω`)

以上!

参考にしたサイト様