はじめに
Supabaseで個人開発をしていると、必ずと言っていいほどぶつかる壁があります。
それが RLS(Row Level Security) です。
最初は順調に開発が進んでいたのに、ある日突然こうなります。
「データが取得できない」
「INSERTが通らない」
「ログインしているのに権限エラー」
SQLも正しいし、テーブルも存在するんだけど動かない。
この記事では、Supabaseで個人開発をするなら絶対に理解しておくべき RLSの基本とハマりポイントを解説します。
RLSとは何か
RLSは Row Level Security(行レベルセキュリティ) の略です。
簡単に言うと、
「このユーザーはこの行のデータだけ触っていい」
というルールを データベース側で管理する仕組みです。
例えばSNSアプリの場合。
user_id post
1 hello
2 supabase
このとき
ユーザー1 → 自分の投稿だけ見れる
ユーザー2 → 自分の投稿だけ見れる
こういう制御をします。
普通のバックエンドだと
WHERE user_id = current_user
みたいなコードを書くことになります。
しかしSupabaseではこれをDBのポリシーとして定義します。
なぜSupabaseではRLSが重要なのか
Supabaseは
フロントエンド → 直接DB
という構成です。
つまり
Next.js
↓
Supabase
↓
PostgreSQL
通常のバックエンドがありません。
そのため、DB自体がセキュリティを持つ必要があります。
ここで登場するのがRLSです。
RLSがあることで
- 他人のデータを取得できない
- 他人のデータを更新できない
- 自分のデータだけ触れる
という仕組みが作れます。
一番よくあるRLSのハマりポイント
Supabase初心者が必ずハマるのがこれです。
RLSをONにすると何もできなくなる
例えばこの状態。
RLS: ON
ポリシー: なし
この場合
SELECT ❌
INSERT ❌
UPDATE ❌
DELETE ❌
ポリシーがない = 全部禁止 のため全部拒否されます。
基本のRLSポリシー
例えば
ログインユーザーだけ自分のデータを見れる
ポリシーはこうなります。
CREATE POLICY "Users can view own data"
ON profiles
FOR SELECT
USING (auth.uid() = user_id);
ログインユーザーID = テーブルのuser_id
のときだけアクセス許可。
Supabaseでは
auth.uid()
でログインユーザーIDが取れます。
INSERTのポリシー
INSERTは
WITH CHECK
を使います。
CREATE POLICY "Users can insert own data"
ON profiles
FOR INSERT
WITH CHECK (auth.uid() = user_id);
自分のuser_idだけ登録できる
UPDATEのポリシー
UPDATEは
CREATE POLICY "Users can update own data"
ON profiles
FOR UPDATE
USING (auth.uid() = user_id);
これで自分のデータだけ更新可能になります。
個人開発でよくあるミス
個人開発ではこれが多いです。
ミス①
RLS ONにしてポリシーなし
結果
permission denied
ミス②
service_role_keyをフロントに置く
これは危険で、service_role_keyはRLSを無視できるためDBフルアクセスとなります。
フロントに置くのはNGです。
ミス③
anon keyとservice keyの混同
Supabaseには2つのキーがあります。
anon key
→ フロント用
service_role_key
→ サーバー用
これを間違えると
セキュリティ事故になります。
個人開発でよくあるのが
- とりあえず開発
- RLS後から追加
ですが、最初にRLS設計する方が楽です。
理由は
- user_id設計
- auth設計
- テーブル設計
全部関係するからです。
まとめ
Supabaseで個人開発をするならRLSは避けて通れません。
むしろ、RLSを理解すると
- 安全なDB
- シンプルなバックエンド
- セキュアなアプリ
が作れるようになります。
Supabaseの設計はRLSから始まると言ってもいいくらい重要です。
もしこれからSupabaseで個人開発をするならまず最初にRLSを理解することをおすすめします。