第15章:Custom Claims入門(ロールを“トークンに埋める”)🎫🔐
この章はひとことで言うと👇 **「管理者フラグ(ロール)を“ユーザーのIDトークン”に刻印して、アプリ全体の門番に使えるようにする」**回です✨ (UIでボタンを隠すだけ🙈じゃなく、仕組みで弾く🛡️のが目的!)
1) まずは超イメージ図🧠✨
- ユーザーがログインすると… IDトークン🎫(身分証みたいなもの)が発行される
- Custom Claims は、その身分証に「あなたはadminです✅」みたいな追加情報を入れる仕組み
- Firestore Security Rules は、その身分証を見て 「通す/止める」 を決められる🚪
Rules側での参照はこんな感じ👇
request.auth.token.admin(adminというクレームを見に行く) (Firebase)

2) 重要ポイントだけ先に⚠️(ここを外すと事故る😱)
✅ Custom Claimsは「クライアントから付けられない」
Custom Claims を付与できるのは Admin SDK(サーバー側の特権環境)だけです。
つまり、Reactアプリ(ブラウザ)にAdmin SDKを入れて付与みたいなのはNG🙅♂️(危険すぎ) (Firebase)

✅ 付与しても、すぐ反映されない(トークン更新が必要)🔄
Custom Claimsは 次に発行されるIDトークンに入ります。
なので付与直後は、ユーザー側で トークンの強制更新が必要になることが多いです(後で手を動かします) (Firebase)

✅ 入れられるサイズに上限がある(1000バイト)📦
Custom Claimsは 最大1000バイト。大きいデータやプロフィール全部を入れる場所じゃないです🙅♀️
「admin: true」みたいな 小さいフラグ向き! (Firebase)

✅ 予約語っぽいクレーム名は使えない🧨
勝手に sub とか iat とか、JWTの標準っぽい名前を使うとトラブルになりやすいです。
Firebase側でも「予約されてるクレーム名がある」注意が出ています(Custom Claimsのドキュメントに記載あり) (Firebase)
3) 手を動かす🧑💻✨:Custom Claims を付けて、Reactで確認する
ここからは 最短で体験します🔥 ゴールは👇 **「自分のUIDに admin=true を付けて、React側で『付いた!』を確認」**です✅
Step A:React側に「クレーム確認パネル」を作る🔍🪪
ログイン後に、今のユーザーが持つクレームを表示します。
(ポイント:getIdTokenResult() で claims が見えます)
// claimsDebug.ts (どこでもOK:コンポーネント内でも可)
import { getAuth, getIdTokenResult } from "firebase/auth";
export async function loadClaims(forceRefresh = false) {
const auth = getAuth();
const user = auth.currentUser;
if (!user) return { uid: null, claims: null };
// forceRefresh=true で「新しいトークンを取り直す」🌀
const tokenResult = await getIdTokenResult(user, forceRefresh);
return { uid: user.uid, claims: tokenResult.claims };
}
表示例(どこかの画面で)👇
- uid:
xxxxx - claims:
{ admin: true, ... }みたいになったら成功🎉
「付与したのに表示されない😢」ときは、あとで出てくる forceRefresh=true を試します🔄 (Firebase)
Step B:Admin SDKで「admin=true」を付与する(最短の1回作業)🔧👑
ここは サーバー側の特権です。初心者でもやりやすいのは👇 ✅ Windows上で、1回だけ“管理者付与スクリプト”を実行(ローカルのNodeでOK)
Admin SDKの前提(2026の目安):
- Admin Node.js SDK:Node.js 18+ (Firebase) (Cloud Functions側のNodeは 20 / 22 が選べて、18はdeprecated) (Firebase)
- Admin Python SDK:Python 3.9+(推奨3.10+、3.9 deprecated) (Firebase)
- Admin .NET SDK:.NET 6+(推奨 .NET 8+、6/7 deprecated) (Firebase)
1) 必要なもの📌
- Firebase Admin SDK用の サービスアカウント認証情報(JSON) (Admin SDKはこれでFirebaseと特権通信します) (Firebase)
2) スクリプト例(TypeScript)🧩
// tools/grant-admin.ts
import fs from "node:fs";
import { initializeApp, cert } from "firebase-admin/app";
import { getAuth } from "firebase-admin/auth";
const serviceAccountPath = "./serviceAccountKey.json"; // 置いた場所に合わせてね
const serviceAccount = JSON.parse(fs.readFileSync(serviceAccountPath, "utf8"));
initializeApp({ credential: cert(serviceAccount) });
const uid = process.argv[2];
if (!uid) {
console.error("使い方: node tools/grant-admin.ts <UID>");
process.exit(1);
}
await getAuth().setCustomUserClaims(uid, { admin: true });
console.log("✅ admin=true を付与しました:", uid);
// 全削除したいとき(全部のCustom Claimsを消す)👇
// await getAuth().setCustomUserClaims(uid, null);
setCustomUserClaims(uid, null)で「そのユーザーのCustom Claimsを全消し」できます🧹 (Firebase)
※ firebase-admin のセットアップや「認証情報ファイルが必要」という話は Admin SDKの公式手順にあります (Firebase)
Step C:React側で「トークン強制更新」して確認する🔄✅
付与直後は、React側でこうします👇
import { loadClaims } from "./claimsDebug";
const before = await loadClaims(false);
console.log("before", before);
const after = await loadClaims(true); // 👈 ここが大事!
console.log("after", after);
after.claims.admin === true になったら勝ち🎉🎉🎉
この「強制更新が必要」って話は公式にも書かれてます (Firebase)
4) (プレビュー)Rules側でどう見える?🛡️👀
次の章(第16章)でガッツリやりますが、Custom ClaimsはRulesでこう見えます👇
// firestore.rules(プレビュー用)
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /adminOnly/{docId} {
allow read, write: if request.auth != null
&& request.auth.token.admin == true;
}
}
}
request.auth.token でトークンの中身(claims)を参照できます (Firebase)
5) よくある事故パターン集😂💥(先に踏んでおこう)

事故①:付与したのに admin が見えない😱
原因トップはこれ👇
- トークン更新してない(forceRefreshしてない) (Firebase)
対策✅
getIdTokenResult(user, true)を使う(または再ログイン)
事故②:クレームに色々入れすぎる📦💣
Custom Claimsは 1000バイト上限。 「表示名」「設定」「権限リスト全部」みたいなのは入れない🙅♂️ (Firebase)
対策✅
- 最小フラグだけ(例:
admin: true,role: "editor"程度) - それ以上は Firestoreに置いて、Rulesは“入口の判定”だけに使う(第17章で比較します)
事故③:クレーム名で地雷を踏む🧨
JWTの標準クレームっぽい名前や予約されてる名前を使うと危険。 公式も「予約されているクレーム名がある」注意をしています (Firebase)
対策✅
admin,roles,tier,staffみたいな 素朴な名前にする
6) AI活用コーナー🤖✨(Antigravity / Gemini CLI)
Custom Claimsは「仕組み」はシンプルだけど、実装のミスが致命傷になりがち😇 だからAIはめちゃ便利。ただし…最終レビューは人間の仕事👀✅
✅ Antigravityでやると強いこと🧠⚡
Firebase MCP server を Antigravity に追加して、エージェントに「作業計画→実装→手順の説明」までやらせられます (The Firebase Blog)
おすすめ依頼文(コピペOK)👇
-
「Custom Claimsで
admin: trueを付与する“安全な運用”を作りたい。- 付与はAdmin SDKだけ、2) 付与後のトークン更新、3) 権限付与の監査ログ案、まで含めて設計して」
✅ Gemini CLI(Firebase拡張)で“叩き台”を速攻で作る💨
Firebase拡張を入れると、Firebase MCP serverの機能が使えます (Firebase)
さらにプロンプトカタログのコマンド(例:/firebase:init)も使えます (Firebase)
そして特にセキュリティルール生成は便利だけど、重要注意⚠️
- Rulesは自動追従で更新されない(1回実行の生成)
- 必ずテストしてからデプロイ
- Admin SDK利用時はRulesが効かないので、バックエンド側で認可が必要 (Firebase)
Custom ClaimsまわりでAIに頼むなら👇
- 「React側でclaimsを表示するコンポーネントを書いて」
- 「Admin SDKで
setCustomUserClaimsを使う最小スクリプトを書いて(JSON鍵の扱い注意も入れて)」 - 「“付与→トークン更新→反映確認”のチェックリストを作って」
7) ミニ課題🎯(10分)
- 自分のUIDを表示できる✅
- Admin SDKで
admin=trueを付ける✅ - Reactで
forceRefresh=trueして、claims.admin === trueを確認✅ - できたら
setCustomUserClaims(uid, null)で削除して、再びadminが消えるのも確認🧹 (Firebase)
8) チェック✅(合格ライン)
- Custom Claimsは「サーバー(Admin SDK)だけ」から付与できると説明できる (Firebase)
- 「付与直後に反映されない=トークン更新が必要」を体で理解した (Firebase)
- Claimsに“大量の情報”を入れない理由(1000バイト)を言える (Firebase)
- 次章で
request.auth.token.adminをRulesに組み込める準備ができた (Firebase)
次の第16章では、ここで作った admin を使って RulesでRBAC(ロール制御)を完成させます👑🛡️
「adminだけ見えるコレクション」「一般ユーザーは自分の分だけ」みたいな王道パターンを一気に組みますよ🔥