t8.dev

🇺🇸

【Firebase】カスタムクレーム(Custom Claims)で管理者ユーザーを作る

公開日:2021/09/15
更新日:

はじめに

心理学を使ったTODOアプリを開発している、@takasqrです。

心理学を使ったTODOアプリ | todo8

心理学を使ったTODOアプリ | todo8

  • 特定のユーザーだけ、Firestore、Firebase strageのアクセス権限を強くしたい
  • 特定のユーザーだけアクセスできるページを作りたい

といった、Authenticationのユーザーにラベルを付けたい時にFirebase Admin SDKのクレームを使うと便利です。

導入

カスタムクレームをセットする。

admin
  .auth()
  .setCustomUserClaims(uid, { admin: true })
  .then(() => {
    // 
  });

例だとAdminというクレームに対してtrueを設定しています。

クライアントで取得するには、

firebase.auth().currentUser.getIdTokenResult()
  .then((idTokenResult) => {
     // Confirm the user is an Admin.
     if (idTokenResult.claims.admin) {
       // adminがtrueだったら
     } else {
       // adminがfalseだったら
     }
  })
  .catch((error) => {
    console.log(error);
  });

セキュリティルールの例。

firestore.rules
match /test/{test} {
      allow read: if request.auth.token.admin == true;
      allow create: if request.auth.uid != null;
    }

これはtestコレクションにFirebase Authのユーザーならだれでもデータを作ることができる。だが、データを読み取るにはadminクレームを持っているユーザーじゃなければならない。

という例。

応用

Firestoreにuidを登録すると、自働的にカスタムクレームを登録してくれる関数です。 Firebase Functionsにデプロイします。

CustomClaimsEx.js
const functions = require('firebase-functions')
const admin = require('firebase-admin')

exports.set = async function (uid, claims) {
  let returnValue = null
  const user = await admin.auth().getUser(uid)
  const updatedClaims = user.customClaims || {}

  for (const property in claims) {
    if (Object.prototype.hasOwnProperty.call(claims, property)) {
      updatedClaims[property] = claims[property]
    }
  }
  await admin.auth().setCustomUserClaims(uid, updatedClaims)
    .then(function () {
      returnValue = Promise.resolve(true)
    })
    .catch((error) => {
      functions.logger.error(error)
      returnValue = Promise.resolve(false)
    })
  return returnValue
}
setAdminClaim.js
const functions = require('firebase-functions')
const CustomClaimsEx = require('./CustomClaimsEx')

exports.setAdminClaim = functions.firestore
  .document('adminClaims/{adminClaimsId}')
  .onCreate(async (snap, context) => {
    CustomClaimsEx.set(snap.data().uid, { admin: true })
  })
unsetAdminClaim.js
const functions = require('firebase-functions')
const CustomClaimsEx = require('./CustomClaimsEx')

exports.unsetAdminClaim = functions.firestore
  .document('adminClaims/{adminClaimsId}')
  .onDelete(async (snap, context) => {
    CustomClaimsEx.set(snap.data().uid, { admin: false })
  })

カスタム クレームとセキュリティ ルールによるアクセスの制御 | Firebase

関連記事

firebaseに入門して一年後の使い方
Firebase Authentication(v9)とNextで認証機能を実装する
Firebase Authentication(v9)とNuxtで認証機能を実装する
Firebase Authentication(v9)とReactで認証機能を実装する
Firebase Authentication(v9)とVueで認証機能を実装する
Firestore Liteとは?
【hooks対応版】Firebase Firestore(v9)とNextでデータを操作する
【hooks対応版】Firebase Firestore(v9)とReactでデータを操作する
Firebase Firestore(v9)とNuxtでデータを操作する
Firebase Firestore(v9)とVueでデータを操作する

オススメ記事

5年間ほぼ毎日プログラミングの勉強をするためにやったこと
論文と本から学ぶ、プログラミング独学のコツ
目標達成率を高める if thenプランニングとは!?【本とアプリも紹介】