1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Supabase RLSをFirebase Authを使って有効にする

Last updated at Posted at 2025-08-24

はじめに

SupabaseのRLSをFirebase Authを使っているプロジェクトで有効にしたのでまとめます。
つまずきどころが多く大変だったので、誰かの参考になれば嬉しいです。

そもそもRLSとは

RLS(Row Level Security)は、PostgreSQLのセキュリティ機能です。
データベースの行レベルでアクセス制御を行う仕組みのことを指します。
テーブル全体へのアクセス制御ではなく、特定の行(レコード)に対してユーザーごとに異なるアクセス権限を設定できます。

Supabase Authを使っているアプリケーションなら簡単に設定ができるのですが、今回はFirebase Authでやってみます。

前提条件

  • Firebase Authを使用していること
  • Supabaseをデータベースとして使用していること

設定手順

基本的には公式ドキュメントに書いてあります。
本記事も公式ドキュメントに従って手順を踏んでいきます。

1. Supabase側でThird-Party Authを有効にする

Supabaseにログインし、Authentication -> Sign In /Providers -> Third-Party Authを有効にします。
Third-Party AuthenticationからFirebaseを選択し、ご自身のFirebaseのProject IDを入力します。

2. FirebaseユーザーにRoleを追加する

ユーザーのアカウントのカスタム属性を変更します。
ドキュメントに詳細は書いてありますが、ユーザーに対してauthenticatedを付与することでデータベースルールを適用できるようです。

新規追加されたユーザーにauthenticatedを割り当てる

functions/index.js

const functions = require('firebase-functions');
const admin = require("firebase-admin");

admin.initializeApp();

exports.setCustomUserClaims = functions.auth.user().onCreate(async (user) => {
  try {
    if (user.email) {
      await admin.auth().setCustomUserClaims(user.uid, { 
        role: "authenticated"
      });
    }
  } catch (error) {
    console.error("Error setting custom claims:", error);
  }
});

以下を実行し、functionsを有効にします。

firebase deploy --only functions

既存ユーザーにauthenticatedを割り当てるスクリプト

const { initializeApp } = require('firebase-admin/app');
const { getAuth } = require('firebase-admin/auth');

initializeApp();

async function setRoleCustomClaim() {
  let nextPageToken = undefined;
  
  do {
    const listUsersResult = await getAuth().listUsers(1000, nextPageToken);
    nextPageToken = listUsersResult.pageToken;
    
    await Promise.all(listUsersResult.users.map(async (userRecord) => {
      try {
        await getAuth().setCustomUserClaims(userRecord.uid, {
          role: 'authenticated'
        });
        console.log(`Role set for user: ${userRecord.uid}`);
      } catch (error) {
        console.error(`Failed to set role for user ${userRecord.uid}:`, error);
      }
    }));
  } while (nextPageToken);
}

setRoleCustomClaim().then(() => process.exit(0));

これで全てのユーザーに対してデータベースルールが適用されます。

3. Supabaseクライアントを設定

アプリケーションでSupabaseクライアントを作成している箇所で、Firebaseのユーザーのtokenを渡すようにします。

import { createClient } from '@supabase/supabase-js'
import { getAuth } from 'firebase/auth'

const auth = getAuth()

const supabase = createClient(
  'https://your-project.supabase.co',
  'your-anon-key',
  {
    accessToken: async () => {
      const user = auth.currentUser
      if (user) {
        return await user.getIdToken(false) // 通常はfalseでキャッシュを利用
      }
      return null
    }
  }
)

4. SupabaseのRLSを有効にする

SupabaseのGUIからRLSを有効にします。
続いて、GUIのSQLエディターから対象のテーブルに対してRLSポリシーを作成します。

まずはSELECTできるようにします。

CREATE POLICY "Enable read access for own data"
ON "public"."users"
FOR SELECT
TO authenticated
USING (uid = (auth.jwt() ->> 'sub'));

そのテーブルのuidと、現在テーブルにアクセスしているユーザーが一致しているかをチェックしています。

UUIDの型の不一致で詰まったのでうまくいかないときは以下を試してみてください。

-- uid列をtext型に変更することを推奨
ALTER TABLE "public"."users" ALTER COLUMN uid TYPE text;

-- または、キャストして比較
USING (uid::text = (auth.jwt() ->> 'sub'))

正しく設定ができていれば、uidが一致しているユーザーのみの行が取得できるはずです。

最後に

初めての技術でつまずきどころが多く時間がかかってしまいましたが、なんとか実装できました。
終わってみると必要なことは全て公式ドキュメントに書いてあるのだと分かりますが、初めての概念があると理解が追いつかず苦戦しました。

特にFirebaseのRoleの設定とRLSの見慣れないポリシー設定のSQLはとっつきにくいので、同じように悩まれている方の参考になれば嬉しいです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?