👥

Firebase Custom Claimでユーザーのロール管理

2022/02/24に公開

前提

  • 管理者、講師、ユーザーの3ロールが存在するWebアプリ
  • それぞれ使用する画面が分かれていて、ログイン時にロールによって制御する必要がある
  • それぞれ新規アカウント作成機能あり

やりたいこと

  • 管理者、講師、ユーザーの3ロールでログイン画面を分けて、ロールごとのログイン制御をしたい

解決策

  • Firebase Authenticationで保持しているユーザーに対して、独自の属性を付与することが可能なCustom Claimというものがあるらしい。

  • 管理者、講師、ユーザーそれぞれが新規作成されたタイミングでCustom Claimをセットすれば良さそう

  • admin権限でしか利用できないみたいなので、functionsで実装する。

  • functions配下にカスタムクレームをセットする処理を書く

    const functions = require('firebase-functions')
    const admin = require('firebase-admin')
    
    admin.initializeApp()
    
    // 管理者ドキュメント作成時に発火
    exports.setAdminClaim = functions
      .region('asia-northeast1')
      .firestore.document('/adminUsers/{adminUserId}')
      .onCreate(async (snap, context) => {
        const customClaims = {
          admin: true,
        }
    		// 取得したドキュメントIDをuidとして指定する
        setCustomClaim(context.params.adminUserId, customClaims)
      })
    
    const setCustomClaim = (uid, customClaims) => {
      try {
        // 新規作成されたuidにカスタムクレームを設定する
        admin.auth().setCustomUserClaims(uid, customClaims)
        console.log('set customClaim')
    
        // リアルタイムにデータベースを更新し、クライアントに通知して強制的に更新させる
        const metadataRef = admin.getDatabase().ref('metadata/' + uid)
    
        // リフレッシュタイムを現在のUTCタイムスタンプに設定する
        metadataRef.set({ refreshTime: new Date().getTime() })
      } catch (error) {
        console.log(error)
      }
    }
    

上記の処理は、firestoreの管理者ドキュメントが作成されたタイミングでexports.setAdminClaimで発火させている。

講師、ユーザーも同様に記述すれば良さそう。

無事にロールごとのログイン制御ができた。

所感

  • Authenticationの管理画面上でCustom Claimの情報を確認できないので、そこが微妙に不便だなと感じた。

  • とはいえ、簡単にロール管理からのログイン制御が実装できたのでメリットのほうが大きい気がする

参考サイト

https://firebase.google.com/docs/auth/admin/custom-claims

https://qiita.com/zaburo/items/cd078d768bd9fd239bf4

https://qiita.com/marutaku0131/items/cafd27ee30a27f6b84a0

Discussion