2
1

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 を基本から一歩づつ理解する(Row Level Security 編)

Last updated at Posted at 2025-03-04

はじめに

新しいサービスを生み出していく際に、はじめから重厚長大な作りをすることは少なくなってきているかと思います。はじめはスピーディにサクッと作りたい、でも大きくなってきたらキッチリ作りたい。「サクッと」から「キッチリ」へ切り替える際に、データ構造がガラッと変わってしまうとサービスを育てていく時の課題になるのではないでしょうか。

do-the-right-thing-1024x458.png

(出典)正しいものを正しくつくる

「サクッと」React をはじめとしたフロントエンドを開発する際に、バックエンドには FirebaseAmplify などを選択することが多いかと思います。私も両方とも好きでよく使っています。しかしながら基本的には NoSQL です。RDB で「サクッと」バックエンドを提供してくれるものが Supabase です。

Supabase は「The Open Source Firebase Alternative / オープンソースの Firebase の代替」と自らを謳っており、慣れ親しんだリレーショナル・データベース(PostgreSQL)でありながら使いやすい BaaS(Backend as a Service)なのです。

本稿では、手を動かしながら Supabase を基本から一歩づつ理解していきたいと思います。前回は Database に触れました。今回は Row Level Security を深堀りしていきたいと思います。

Supabase とは

読み方は「スーパーベース」と読みます。
主要な機能は以下です。

  • Database
    • Row Level Security ← イマココ
  • Auth
  • Storage
  • Realtime
  • Edge Functions

Row Level Security (RLS) とは

Supabase はオープンソースの PostgreSQL を利用しています。30 年以上にわたって開発・改善されてきたオブジェクトリレーショナルデータベースシステムで、信頼性、機能の堅牢性、パフォーマンスの面で高い評価を得ています。

Row Level Security (RLS) は PostgreSQL の機能です。RLSは、テーブル内の行へのアクセスを制御する機能です。RLS は SQL ルールを記述できます。Supabase の Auth 機能と組み合わせることでブラウザからデータベースまでの一貫した権限制御を行うことができます。

image.png

(出典)Supabase README.jp.md

注意点

Supabase では、RLS を有効にしている限り、ブラウザから便利かつ安全なデータ アクセスが可能になります。

公開されたスキーマに格納されているすべてのテーブルでは、RLS を常に有効にする必要があります。デフォルトでは public スキーマです。

ダッシュボードのテーブル エディターで作成されたテーブルでは、RLS がデフォルトで有効になっています。生の SQL または SQL エディターでテーブルを作成する場合は、RLS を自分で有効にすることを忘れないでください。

alter table <schema_name>.<table_name>
enable row level security;

(出典)Supabase Doc > RLS

Policies

Postgres には Policies というルール機能があります。各ポリシーはテーブルに添付され、テーブルへアクセスするたびにポリシーが実行されます。

例)todos テーブルに SELECT 文を投げる時に、認証しているユーザーIDと todos テーブルのユーザーIDが一致しているかを確認するポリシー

create policy "Individuals can view their own todos."
on todos for select
using ( (select auth.uid()) = user_id );

todos テーブルへ SELECT 文を投げる時には WHERE 句が追加された状態になる。

select *
from todos
where auth.uid() = todos.user_id;
-- Policy is implicitly added.

(出典)Supabase Doc > Policies

Supabase で RLS を有効にする

Supabase はテーブルを作成すると自動的に API 経由で CRUD できるようになります。RLS を有効にすると、ポリシーを作成するまでは公開キー(anon key)を使用してAPI経由でデータにアクセスできなくなります。Supabase の GUI で設定も出来ますが、環境保持の観点から SQL を作成して Git 管理をおすすめします。

alter table "table_name" enable row level security;

books テーブルで RLS が未設定のため GUI で有効にしていきます。
(※デフォルトではRLSは有効な状態になってますが説明のため)

image.png

image.png

image.png

有効になりましたのでポリシーを設定します。
Add RLS policy > Create policy
image.png

image.png

SELECT 文のポリシーで Enable read access for all users を books テーブルに設定します。

image.png

image.png

alter policy "Enable read access for all users"

on "public"."books"
to public
using (
  true
);

認証済ロールと未認証ロール

Supabase はすべてのリクエストを認証済/未認証という Postgres のロールに分類します。

  • authenticated : 認証済リクエスト(ユーザーがログインしている)
  • anon : 未認証リクエスト(ユーザーがログインしていない)

匿名ユーザ(anonymous user)とanonキーの違い

anon という Postgres ロールは、Supabase Auth の 匿名ユーザ とは異なります。匿名ユーザは「authenticated 認証されたロール」としてデータベースへアクセス可能です。
JWT の claim で is_anonymous をチェックすることで 永続ユーザ と区別できます。

上記は公式の解説になりますが、少し補足します。

1. anon ロール
Supabase では、PostgreSQL のロール(ユーザーのようなもの)として anon ロール を用意しています。このロールは、認証されていない(未ログインの)ユーザーがデータベースへアクセスするときに使用します。

anon ロールは Supabase の API キー (anon key) を使ったアクセス に関連しています。例えば、anon キーを使って直接 Supabase の REST API を叩くと、そのリクエストは anon ロールとして処理されます。

2. Supabase Auth の「匿名ユーザー」
Supabase Auth では「匿名ユーザー(anonymous user)」という概念があります。ログインはしているが、匿名として扱うユーザーを指します。

Supabase Auth の「匿名ユーザー」は 認証済み(authenticated) の状態になり、データベースでは authenticated ロールとして動作します。
しかし、通常のユーザーとは異なり、JWT の is_anonymous クレーム(JWT の中に含まれる情報)を見れば、匿名ユーザーかどうかを判別できます。

項目 anon ロール 匿名ユーザー(anonymous user)
認証の有無 認証なし 認証あり
使われるロール anon authenticated
どこで使われる? anon キーでのアクセス Supabase Auth で匿名ログイン
JWT で識別可能? ×(そもそも JWT なし) is_anonymous クレームをチェック

例1)認証なしの API アクセスは anon ロールとなる

const { data } = await supabase
  .from('public_table')
  .select('*');

例2)Supabase Auth の匿名ユーザーは、JWT の is_anonymous クレームが true になる。

const { user } = await supabase.auth.signInAnonymously();
console.log(user);

要するに、Supabase では 「認証されていないアクセス(anon ロール)」 と 「認証はされたが匿名なユーザー(Supabase Auth の anonymous)」 は異なるものとして扱うということです。

(出典)Supabase Doc > Authenticated and unauthenticated roles

Policies の作成方法

SELECT, INSERT, UPDATE, DELETE, View に対応するポリシーの作成方法があります。公式ドキュメントや Supabase ダッシュボード画面にサンプルとなるポリシーのSQLがありますので、そちらをご参照ください。

image.png

image.png

(出典)Supabase Doc > Creating policies

ヘルパー関数

ポリシーを作成するためのヘルパー関数が準備されています。
これまでも目に入ってたかと思いますが auth.uid()auth.jwt() などです。詳しくは公式ドキュメントを参照ください。

(出典)Supabase Doc > Helper functions

RLS の制約なしにデータへアクセスする方法(管理専用)

RLS は公開サイトやブラウザ・ユーザーからのアクセスを想定した権限制御です。サーバー側で閉じたネットワーク内での管理用途では RLS をバイパス(無視)してデータにアクセスしたいユースケースでは Service Key を使います。

Service Key でのバイパス

Supabase には Service Key という特別な API キーがあります。このキーを使うと RLS を無視して データにアクセスできます。ただし、これは 管理用(バックエンド)専用 であり、ブラウザやユーザーには絶対に公開してはいけません。

Service Key を使っても、サインインしたユーザーの RLS は適用されます。つまり、RLS を完全にバイパスしたいなら、ユーザーの認証を使わないシステム的な処理 にする必要があります。

※PostgreSQL の bypassrls 権限を使えば、RLS を完全に無視できますが漏洩した場合にセキュリティリスクがありますので推奨はしません。

(出典)Supabase Doc > Bypassing Row Level Security

性能面での推奨

RLS は権限制御において便利ですが、性能に影響します。
インデックスの他、Supabase ならではの Tips が公式ドキュメントに記載されていますのでご参照ください。

(出典)Supabase Doc > RLS performance recommendations

参考

解説しきれませんでしたが、以下もご参考ください。

おわりに

以上で Row Level Security (RLS) 編を終わります。
次回は Auth 編・・・と言いたいところですが Column Level Security(列レベルセキュリティ)を深堀りしていきます。

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?