GoogleアカウントやTwitterなど以外でもFirebase Authを使いたいなと思い、
カスタムトークン認証を試してみるを試してみたときの備忘録
認証の流れ
全体の流れはこんな感じ。
- 外部の認証でUIDを取得する
- サーバ側: firebase-adminのcreateCustomToken()でカスタムトークンを作成する
- クライアント側: 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のサービスエージェントも表示されないので、チェックを入れる。
iam.serviceAccounts.signBlob
の権限を含むロールは、
「サービスアカウントトークン作成者」なので、変種ボタンからロールを追加する。
これで、Cloud Functions上でカスタムトークンが作成できるように(´ω`)
以上!