Firebase Custom Claims 사용법: 관리자 권한 구분하기

··설명 약 5분·작성: 해비·블로그 소개

Firebase Custom Claims로 관리자 권한을 부여하고 전파·회수를 어떻게 확인하나요?

Custom Claims는 신뢰하는 서버가 사용자 ID token에 넣는 작은 권한 정보입니다. 화면의 관리자 표시만으로 접근을 허용하지 말고 서버·Rules에서도 집행해야 합니다.

적용 조건·범위: 기존 ID token은 즉시 바뀌지 않습니다. 클라이언트가 getIdTokenResult(true)로 새 토큰을 받거나 재로그인해야 새 claim이 보입니다. revokeRefreshTokens는 기존 ID token을 모든 서비스에서 즉시 무효화하는 스위치가 아닙니다. 자체 API는 verifyIdToken(idToken, true)로 취소를 검사하고, Rules에는 필요한 경우 공식 문서의 취소 시각 검사 패턴을 별도로 설계합니다. 민감 권한의 즉시 회수에는 이 경계가 중요합니다.

본문 근거: firebase.google.com/docs/auth/admin/custom-claims · firebase.google.com/docs/auth/admin/manage-sessions

학습 목표와 사전 지식

목표: 관리자 claim의 부여·전파·집행·회수를 서로 다른 단계로 설계합니다.
사전 지식: Firebase Auth ID token, Admin SDK 서버 환경, Security Rules

Custom Claims는 서버가 서명한 ID token에 담는 작은 권한 정보입니다. 화면의 isAdmin 값은 표시용이고 실제 허용은 Rules나 서버 verifyIdToken 이후에 결정합니다. 프로필 데이터나 비밀값을 claim에 넣지 않습니다.

권한을 부여할 수 있는 사람부터 정하기

다음 스크립트는 신뢰 관리자만 실행하는 서버 관리 도구입니다. 사용자가 UID를 보내면 누구나 claim을 부여하는 공개 API로 옮기면 안 됩니다. applicationDefault 자격 증명은 신뢰 실행 환경에서 공급하고 클라이언트 번들에 Admin SDK 키를 넣지 않습니다.

scripts/admin-role.mjs · 전체 관리 모듈; 실제 권한 변경 명령이므로 개발 사용자에 한해 실행

import { applicationDefault, initializeApp } from 'firebase-admin/app';
import { getAuth } from 'firebase-admin/auth';

initializeApp({ credential: applicationDefault() });
const uid = process.env.TARGET_USER_UID;
const action = process.argv[2];
if (!uid || !['grant', 'revoke'].includes(action)) {
  throw new Error('대상 UID와 grant 또는 revoke가 필요합니다.');
}
const auth = getAuth();
const user = await auth.getUser(uid);
const claims = { ...(user.customClaims ?? {}) };
if (action === 'grant') claims.admin = true;
else delete claims.admin;
await auth.setCustomUserClaims(uid, claims);
if (action === 'revoke') await auth.revokeRefreshTokens(uid);
console.log('권한 변경 요청을 완료했습니다.');
관리자 역할을 Admin SDK에서 부여하고 ID token, Security Rules와 서버 검증으로 전달하는 흐름

덮어쓰기와 경쟁 조건

setCustomUserClaims는 전체 claim 객체를 교체합니다. 기존 객체를 복사하면 다른 키의 단순 누락은 막지만 두 관리 작업이 동시에 읽고 쓰는 경쟁까지 해결되지는 않습니다. 권한 변경을 한 서버 경로로 모으고 변경 주체·사유를 기록하세요. claim은 1000바이트 제한이 있고 접근 제어에 필요한 작은 값만 넣습니다.

토큰 전파와 즉시 회수를 혼동하지 않기

기존 ID token은 즉시 바뀌지 않습니다. 클라이언트가 getIdTokenResult(true)로 새 토큰을 받거나 재로그인해야 새 claim이 보입니다. revokeRefreshTokens는 기존 ID token을 모든 서비스에서 즉시 무효화하는 스위치가 아닙니다. 자체 API는 verifyIdToken(idToken, true)로 취소를 검사하고, Rules에는 필요한 경우 공식 문서의 취소 시각 검사 패턴을 별도로 설계합니다. 민감 권한의 즉시 회수에는 이 경계가 중요합니다.

서버 requireAdmin 함수 · 부분 예제; Admin 초기화와 HTTP 401/403 변환은 호출 서버에서 처리

import { getAuth } from 'firebase-admin/auth';

export async function requireAdmin(idToken) {
  const decoded = await getAuth().verifyIdToken(idToken, true);
  if (decoded.admin !== true) throw new Error('forbidden');
  return decoded.uid;
}
Firebase Custom Claims를 Firestore Rules와 백엔드 ID token 검증에서 강제하는 구조

개발 계정 세 개로 비교하기

비로그인·일반 사용자·관리자를 분리합니다. 일반 사용자가 자신의 프로필 role을 admin으로 바꾸더라도 관리자 API가 거부되어야 합니다. 관리자 부여 전·새 토큰 발급 후·회수 후를 나누고 기존 토큰을 재사용하는 경우도 검사합니다. claim이 없는 경우 false로 취급하며 브라우저 상태를 임의 변경해도 서버 권한은 달라지지 않아야 합니다.

권한 변경 시점별로 결과를 구분하기

관리 스크립트를 실제 계정에 실행하기 전에 다음 명령으로 문법만 확인하세요. 이 명령은 권한을 바꾸지 않습니다.

node --check scripts/admin-role.mjs
시점 클라이언트의 기존 ID token 새 토큰/서버 검사에서 확인할 것
부여 직전 admin claim 없음 일반 사용자로 거부
grant 관리 작업 직후 기존 토큰에는 아직 admin 없음 getIdTokenResult(true)로 새 토큰을 받으면 admin: true 여부 확인
revoke 관리 작업 직후 이전 관리자 토큰에는 admin이 남을 수 있음 verifyIdToken(idToken, true)를 쓰는 자체 서버는 취소 여부도 검사
재인증·새 토큰 발급 후 이전 토큰을 사용하지 않음 새 토큰에는 admin이 없어야 하고 관리자 요청 거부

이 표는 예상 상태입니다. Rules는 인증 요청에 실린 토큰의 claim을 평가하므로, revokeRefreshTokens만 호출했다고 모든 기존 ID token이 즉시 거부된다고 말할 수 없습니다. 엄격한 즉시 회수 요구가 있으면 Rules의 취소 시각 검사나 서버의 checkRevoked 경로를 별도 설계·시험하세요. grant·revoke 자체는 신뢰 관리자 실행 환경에서만 하고, 실제 테스트는 개발 사용자 UID로 분리하세요. 이 편집에서는 관리 모듈 Node 문법만 통과했으며 권한 변경·서버 검증은 실행하지 않았습니다.

직접 확인할 결과

관리 모듈 Node 문법 확인
부여/회수/기존 토큰 시나리오 기록
실제 관리자 계정·서버 검증 미실행

검증 범위와 기준일

공식 문서 확인일: 2026-09-13. 웹 SDK 예제는 모듈형 API 기준입니다. 이 글의 코드·구조 정적 검토와 실제 클라우드 인증·저장·배포 검증을 구분합니다. 본인 개발 Firebase 프로젝트의 실제 인증·권한·배포 요청은 이 편집 환경에서 실행하지 않았습니다.

이어서 학습하기

공식 문서

이 글이 도움이 되었나요?

조회 중

읽음 기록

읽음 — / 전체 20개 · 필수 14개

이 글을 쓴 해비

웹사이트를 제작·운영하고, 개인 서비스와 자동화·AI 도구를 만듭니다. 직접 만들며 배운 내용과 문제 해결 과정을 BlogFlow에 기록합니다.

새 글 받아보기

RSS 리더에서 BlogFlow의 새 글을 확인할 수 있습니다.

RSS 피드 구독하기

댓글 남기기