SupabaseのRow Level Security (RLS) を理解する

Supabaseのデータベースのセキュリティを担う「**Row Level Security**(行レベルセキュリティ)」とは、その名の通り、データベースの各行に対して個別にセキュリティ設定を行う機能です。

Supabaseのデータベースのセキュリティを担う「Row Level Security(行レベルセキュリティ)」とは、その名の通り、データベースの各行に対して個別にセキュリティ設定を行う機能です。

これにより、特定の行に対するアクセスを制限し、より細かいセキュリティ管理が可能となります。

この機能を実現するために、Policy(ポリシー)と呼ばれるセキュリティルールを定義したオブジェクトを使用します。ポリシーを定義し、テーブルに適用することで、どのユーザーがどの操作を実行できるかを行単位で管理できます。

Firebaseに馴染みのある方は、Firestoreの「セキュリティルール」と同様の概念と考えていただければわかりやすいでしょう。

元々はPostgreSQLの機能ですが、Supabaseではコンソールからボタンをクリックするだけで簡単に設定できます。

Row Level Security | Supabase Docs

SupabaseのRLS

細かい認証ルールが必要な場合、PostgresのRow Level Security(行レベルセキュリティ, RLS)に勝るものはありません。

RLS(Row Level Security)は非常に強力で柔軟性があり、複雑なSQLルールを作成して、独自のビジネスニーズに合わせることができます。RLSは、ブラウザからデータベースまでユーザーのセキュリティをエンドツーエンドで保護するために、Supabase Authと組み合わせることができます。

RLSはPostgresの基本機能であり、サードパーティのツールを通じてアクセスされる場合でも、悪意のあるアクターからデータを保護するための「防御の深層化」を提供します。

publicスキーマに作成されたテーブルには、常にRLSを有効にすべきです。これはTable Editorでテーブルを作成すると自動的に行われます。SQL Editorや生のSQLでテーブルを作成する場合は、RLSを自分で有効にすることを忘れないでください。

ポリシー

ポリシーはPostgresのルールエンジンです。ポリシーは一度理解すると簡単です。各ポリシーはテーブルに付属し、テーブルにアクセスされるたびに実行されます。

ポリシーは、すべてのクエリにWHERE句を追加するようなものです。例えば、以下のようなポリシーは…

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

… ユーザーがtodosテーブルから選択しようとするときに以下のように変換されます:

select *
from todos
where auth.uid() = todos.user_id;
-- ポリシーが暗黙的に追加されます。
 

行レベルセキュリティの有効化

任意のテーブルに対してenable row level security句を使用してRLSを有効にすることができます:

alter table "table_name" enable row level security;
 

RLSを有効にすると、ポリシーを作成するまでpublicのanonキーを使用してAPI経由でデータにアクセスできなくなります。

認証済みおよび未認証のロール

Supabaseは各リクエストを以下のロールのいずれかにマッピングします:

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

これらは実際にはPostgresのロールです。これらのロールは、TO句を使用してポリシー内で使用できます:

create policy "Profiles are viewable by everyone"
on profiles for select
to authenticated, anon
using ( true );
 
-- または
 
create policy "Public profiles are viewable only by authenticated users"
on profiles for select
to authenticated
using ( true );
 

匿名ユーザーとanonキーの違い:

anon Postgresロールを使用することは、Supabase Authにおける匿名ユーザーとは異なります。匿名ユーザーはデータベースにアクセスするためにauthenticatedロールを引き受け、JWTのis_anonymousクレームをチェックすることで永続的なユーザーと区別することができます。

ポリシーの作成

ポリシーは単にPostgresテーブルに付属するSQLロジックです。各テーブルにいくつでもポリシーを付けることができます。

Supabaseは、Supabase Authを使用している場合にRLSを簡単にするためのいくつかのヘルパーを提供しています。これらのヘルパーを使用して基本的なポリシーを説明します:

SELECTポリシー

using句を使用してselectポリシーを指定できます。

例えば、publicスキーマにprofilesというテーブルがあり、誰でも読み取れるようにしたいとします。

-- 1. テーブルを作成
create table profiles (
  id uuid primary key,
  user_id references auth.users,
  avatar_url text
);
 
-- 2. RLSを有効にする
alter table profiles enable row level security;
 
-- 3. ポリシーを作成
create policy "Public profiles are visible to everyone."
on profiles for select
to anon         -- 推奨されるPostgresロール
using ( true ); -- 実際のポリシー
 

あるいは、ユーザーが自分のプロファイルだけを見られるようにしたい場合:

create policy "User can see their own profile only."
on profiles
for select using ( (select auth.uid()) = user_id );
 

INSERTポリシー

with check句を使用してinsertポリシーを指定できます。with check式は、新しい行データがポリシー制約に適合することを保証します。

例えば、publicスキーマにprofilesというテーブルがあり、ユーザーが自分自身のためにのみプロファイルを作成できるようにしたい場合、ユーザーIDが挿入しようとしている値と一致することを確認したいとします:

-- 1. テーブルを作成
create table profiles (
  id uuid primary key,
  user_id references auth.users,
  avatar_url text
);
 
-- 2. RLSを有効にする
alter table profiles enable row level security;
 
-- 3. ポリシーを作成
create policy "Users can create a profile."
on profiles for insert
to authenticated                          -- 推奨されるPostgresロール
with check ( (select auth.uid()) = user_id );      -- 実際のポリシー
 

UPDATEポリシー

using式とwith check式の両方を組み合わせることでupdateポリシーを指定できます。

using句は更新を許可するために真である必要がある条件を表し、with check句は更新された行がポリシー制約に適合することを保証します。

例えば、publicスキーマにprofilesというテーブルがあり、ユーザーが自分のプロファイルだけを更新できるようにしたい場合、using句はユーザーが更新対象のプロファイルを所有しているかどうかをチェックし、with check句は更新されたプロファイルが所有条件を満たしていることを確認します:

-- 1. テーブルを作成
create table profiles (
  id uuid primary key,
  user_id references auth.users,
  avatar_url text
);
 
-- 2. RLSを有効にする
alter table profiles enable row level security;
 
-- 3. ポリシーを作成
create policy "Users can update their own profile."
on profiles for update
to authenticated                    -- 推奨されるPostgresロール
using ( (select auth.uid()) = user_id )       -- 既存の行がポリシー式に適合するかチェック
with check ( (select auth.uid()) = user_id ); -- 新しい行がポリシー式に適合するかチェック
 

with check式が定義されていない場合、using式が可視行の決定(通常のUSINGケース)と新しい行の追加を許可するかの決定(WITH CHECKケース)に使用されます。

DELETEポリシー

using句を使用してdeleteポリシーを指定できます。

例えば、publicスキーマにprofilesというテーブルがあり、ユーザーが自分のプロファイルだけを削除できるようにしたい場合:

-- 1. テーブルを作成
create table profiles (
  id uuid primary key,
  user_id references auth.users,
  avatar_url text
);
 
-- 2. RLSを有効にする
alter table profiles enable row level security;
 
-- 3. ポリ
 
シーを作成
create policy "Users can delete a profile."
on profiles for delete
to authenticated                     -- 推奨されるPostgresロール
using ( (select auth.uid()) = user_id );      -- 実際のポリシー
 

ビュー

ビューはデフォルトでRLSをバイパスします。これは通常、postgresユーザーで作成されるためです。これはPostgresの機能であり、security definerでビューが自動的に作成されます。

Postgres 15以降では、anonおよびauthenticatedロールによって呼び出されたときに、基礎となるテーブルのRLSポリシーに従うビューを作成できます。security_invoker = trueを設定します。

create view <VIEW_NAME>
with(security_invoker = true)
as select <QUERY>
 

古いバージョンのPostgresでは、anonおよびauthenticatedロールからのアクセスを取り消すか、公開されていないスキーマにビューを配置することでビューを保護します。

ヘルパー関数

Supabaseは、ポリシーの記述を容易にするためのヘルパー関数を提供しています。

auth.uid()

リクエストを行っているユーザーのIDを返します。

auth.jwt()

リクエストを行っているユーザーのJWTを返します。ユーザーのraw_app_meta_dataカラムまたはraw_user_meta_dataカラムに保存したものは、この関数を使用してアクセスできます。これらの違いを理解することが重要です:

  • raw_user_meta_data - 認証済みユーザーがsupabase.auth.update()関数を使用して更新できます。認可データを保存する場所としては適していません。
  • raw_app_meta_data - ユーザーによって更新されることはありません。したがって、認可データを保存する場所として適しています。

auth.jwt()関数は非常に多用途です。例えば、app_metadataにチームデータを保存している場合、特定のユーザーがチームに所属しているかどうかを判断するために使用できます。例えば、これがIDの配列であった場合:

create policy "User is in team"
on my_table
to authenticated
using ( team_id in (select auth.jwt() -> 'app_metadata' -> 'teams'));
 

JWTは常に「新鮮」であるわけではないことに注意してください。上記の例では、ユーザーをチームから削除してapp_metadataフィールドを更新しても、ユーザーのJWTが更新されるまでauth.jwt()を使用しても反映されません。

また、Authにクッキーを使用している場合は、JWTのサイズに注意してください。一部のブラウザは各クッキーに4096バイトの制限があるため、JWTの合計サイズがこの制限内に収まるようにする必要があります。

MFA

auth.jwt()関数を使用して多要素認証 (MFA)をチェックできます。例えば、少なくとも2つのレベルの認証がある場合にのみユーザーがプロファイルを更新できるように制限することができます(Assurance Level 2):

create policy "Restrict updates."
on profiles
as restrictive
for update
to authenticated using (
  (select auth.jwt()->>'aal') = 'aal2'
);
 

RLSのバイパス

SupabaseはRLSをバイパスするための特別な「サービス」キーを提供します。これらはブラウザで使用したり、顧客に公開したりすることは絶対に避けるべきですが、管理タスクには役立ちます。

Supabaseは、クライアントライブラリがサービスキーで初期化されていても、サインインしたユーザーのRLSポリシーに従います。

また、「bypass RLS」権限を持つ新しいPostgresロールを作成して、行レベルセキュリティをバイパスすることもできます:

grant bypassrls on "table_name" to "role_name";
 

これはシステムレベルのアクセスに役立ちます。この特権を持つPostgresロールのログイン資格情報を共有することは絶対に避けるべきです。

Read more

リアルタイム投票アプリ5選【ライブ配信やイベントで】

リアルタイム投票アプリ5選【ライブ配信やイベントで】

ウェビナーやセミナー、社内研修を実施する際、「参加者が受け身になってしまう」「質問がなかなか出てこない」といった課題を感じたことはないでしょうか。 オンラインでの情報発信が当たり前になった今、一方的な配信だけでは参加者の満足度を高めることが難しくなっています。そこで注目されているのが、リアルタイムで参加者の意見を集約し、その場で結果を共有できる投票・質問ツールです。 本記事では、ライブ配信やイベント、研修などで活用できるリアルタイム投票アプリを5つ厳選してご紹介します。 リアルタイム投票でつながる参加者とイベント リアルタイム投票やQ&A機能を使うと、視聴者や参加者の意見を即座に集計・表示できます。講義や会議の進行を妨げず、参加者全員が自分の意見を簡単に表明できる仕組みです。 従来の挙手による質疑応答では、発言しづらいと感じる参加者も少なくありません。特にオンラインイベントでは、カメラがオンになっていることへの抵抗感や、大人数の前で質問することへのハードルが存在します。 しかし、スマートフォンから匿名で投票やコメントができる仕組みがあれば、参加者は気軽に自分の意見を伝えら

By 阿部 隼也
質問受付ツールの選び方とおすすめ5選を紹介

質問受付ツールの選び方とおすすめ5選を紹介

セミナーや講演会、社内研修などで「質問はありませんか?」と投げかけても、なかなか手が挙がらない経験はないでしょうか。参加者に有益な情報を提供しても、疑問や意見が共有されないまま終わってしまうのは、主催者にとっても参加者にとっても大きな機会損失です。 こうした課題を解決するために注目されているのが「質問受付ツール」です。参加者がスマートフォンから匿名で質問を投稿できるため、発言への抵抗感が下がり、活発なコミュニケーションが生まれます。 本記事では、質問受付ツールの基本機能から、実際に役立つおすすめツール5選、そして選定時に押さえておきたいポイントまで、実務に活かせる情報をまとめて解説します。 質問受付の現場課題 イベントやセミナーの運営で最も頭を悩ませる問題の一つが、参加者からの質問をいかに引き出すかという点です。質問タイムを設けても、会場がシーンと静まり返ってしまい、仕方なく「それでは時間になりましたので」と締めくくる光景は珍しくありません。 この背景には、日本特有の文化的要因も関係しています。大勢の前で発言することへの恥ずかしさ、自分の質問が的外れではないかという不安、他

By 阿部 隼也
オンラインセミナーアプリの選び方。参加者エンゲージメントを高めるポイント

オンラインセミナーアプリの選び方。参加者エンゲージメントを高めるポイント

近年、オンラインセミナーの活用が急速に広がっています。会場のコストや移動時間を気にすることなく、全国・世界中から参加者を集められる点は大きな魅力です。 しかし、せっかく開催しても 「参加者が途中で離脱してしまう」 「ただ見ているだけで反応が薄い」 といった課題を抱えている企業も少なくありません。 本記事では、参加者のエンゲージメントを高め、成果につながるオンラインセミナーアプリの選び方と、実務に役立つ具体的なポイントを解説します。 参加者とのつながりを生むオンライン環境の設計 オンラインセミナーにおける最大の課題は、画面越しの距離感です。会場で直接顔を合わせる機会がないからこそ、参加者が「ただ見ているだけ」にならないような仕組みが求められます。適切なツールと機能選びが、参加者のエンゲージメントを左右します。 従来のオフラインセミナーでは、会場の雰囲気や参加者同士の反応が自然と生まれましたが、オンラインではそうした「空気感」が伝わりにくくなります。だからこそ、双方向のコミュニケーション機能や、参加者の行動データを活用した設計が重要になるのです。 エンゲージメントを高

By 阿部 隼也
参加者の質問を効率的に管理!ZoomウェビナーQ&A機能の使い方を徹底解説

参加者の質問を効率的に管理!ZoomウェビナーQ&A機能の使い方を徹底解説

オンラインでのセミナーやイベントが日常化する中で、Zoomウェビナーを活用している企業が増えています。しかし、ウェビナーの開催で意外と頭を悩ませるのが「参加者からの質問をどう管理するか」という点ではないでしょうか。 セミナーが盛り上がり、次々と質問が寄せられるのは嬉しいことです。一方で、質問が多すぎて整理しきれない、どの質問に優先的に答えるべきか判断に迷う、といった課題も生じます。こうした問題を解決するために役立つのが、ZoomウェビナーのQ&A機能です。 本記事では、ZoomウェビナーのQ&A機能の基本的な使い方から、参加者の質問を効率的に管理する実践的なテクニックまで、詳しく解説していきます。 ZoomウェビナーのQ&A機能とは ZoomウェビナーのQ&A機能は、ウェビナー開催中に参加者が質問を投稿し、主催者側が回答を行うための専用機能です。この機能を使うことで、質問と回答がスレッド形式で整理され、効率的なコミュニケーションが可能になります。 チャット機能との違い Zoomには「チャット機能」もあるため、「Q&A機能とチャット機能の違いは何か」と疑問に思う方も多いで

By 阿部 隼也