stin's blog logo

Firebase Auth, Firestore, Functions for Firebase でサクッと管理者権限を割り振る

公開:


Firebase のユーザーに個別に権限を割り振りたい要件は多そう。すでに似たような記事はたくさんありますが、自分も実装方法を調べたので文章にしておきます。

実装イメージ

Firebase Auth のカスタムクレームを使用します。Firebase ユーザーオブジェクトに独自のプロパティを生やすことができる機能です。

Firestore にユーザー別にどんな権限(=カスタムクレーム)を持っているかを格納しておく user-claims というコレクションを用意します(コレクション名は任意)。

Functions for Firebase で Firestore の user-claims コレクションへの変更イベントをリッスンして、その内容を Firebase Auth のカスタムクレームに同期させます。 user-claims コレクションへの書き込みは Firebase コンソールから直接でも Admin サーバー経由でもいけます。

実装後の使い道

クライアント環境でユーザーに付与されたカスタムクレームを参照して、画面の出し分けに使えたりします。

const isAdminUser = getAuth() .currentUser?.getIdTokenResult(true) .then(idToken => idToken.claims.isAdminUser); // `isAdminUser` の部分は好きなキー名にできる。ただし型はつかない console.log(isAdminUser); // user-claims コレクションで付与した値

また、Callable Functions のリクエスト検証で認証チェックの 1 つとして利用できます。

export const myFunction = functions.https.onCall(async (data, context) => { if (context.auth?.token.isAdminUser !== true) { throw new functions.https.HttpsError( "permission-denied", "The function must be called by admin user.", ); } // do something });

他にも使い道の可能性は無限大です。知らんけど。

実装方法

Firestore の user-claims コレクションに登録されたデータを Firebase Auth のカスタムクレームにセットする処理を Functions が担当しますので、Functions のコードを書いていきます。

user-claims コレクション内のドキュメントデータとカスタムクレームを完全に同期するには、

  • user-claims コレクションにドキュメントが作成されたらカスタムクレームに書き込む
  • user-claims コレクションのドキュメントが更新されたらカスタムクレームに書き込む
  • user-claims コレクションのドキュメントが削除されたらカスタムクレームも削除する
  • ユーザーが削除されたら user-claims コレクションのドキュメントも削除する

の 4 つの処理が必要になります。 user-claims コレクションのドキュメント ID はユーザー ID とします。

export const addUserClaims = functions.firestore .document("user-claims/{docId}") .onCreate(userClaims => getAuth().setCustomUserClaims(userClaims.id, userClaims.data()), ); export const updateUserClaims = functions.firestore .document("user-claims/{docId}") .onUpdate(userClaims => getAuth().setCustomUserClaims(userClaims.after.id, userClaims.after.data()), ); export const removeUserClaims = functions.firestore .document("user-claims/{docId}") .onDelete(userClaims => getAuth().setCustomUserClaims(userClaims.id, null)); export const removeUserClaimDoc = functions.auth.user().onDelete(user => { getFirestore().collection("user-claims").doc(user.uid).delete({ exists: false }); });

尚、本記事ではユーザーが存在するが対応する user-claims のドキュメントは存在しない状態を許容するものとします。

はい、これで Firestore の user-claims にドキュメントを追加すれば同じ ID のユーザーに対して自由に権限が割り振れるようになりました。

あとは Firebase コンソールなり Admin 環境から user-claims にユーザー ID をドキュメント ID としたドキュメントを追加していけばいいでしょう。

ちなみに、わざわざ Functions や Firestore を使わなくても Admin 環境で setCustomUserClaims を呼び出せばいいのですが、Firestore と同期されていれば Firebase コンソールからでも登録削除ができるので便利になりますし、カスタムクレームの内容を Firestore のコレクションで一元管理できるのでわかりやすいです。

まとめ

Firebase Auth, Firestore, Functions for Firebase を組み合わせて、ユーザーに権限を割り振る方法を紹介しました。

実装方法を簡単にまとめると

  • Functions で Firestore の変更イベントを検知して、Firebase Auth のカスタムクレームに書き込む
  • 書き込まれたカスタムクレームをクライアントや Callable Functions で使う

です。

それではよい Firebase ライフを!

記事をシェアBuy Me A Coffee
GitHub で修正をリクエストする
すべての記事一覧へ

このサイトは Google Analytics を使用しています

© stin_factory