Clerkのユーザー情報を使ってSupabase上にあるDBへのアクセス権を管理する
この記事では、ClerkというIDaaSを利用してユーザー情報を管理している場合に、Supabase上にあるデータベースのRow level Securityを設定する方法が紹介されています。SupabaseのJWTを取得し、Clerkと連携する手順や、Supabaseでの関数作成、テーブル設定、RLSの設定方法が紹介されています。実際に導入しなかったものの、Supabase以外のIDaaSを利用しつつRLSの恩恵を受ける方法について学びました。
目次
この記事では、ClerkというIDaaSを利用してユーザー情報を管理している場合に、Supabase上にあるデータベースのRow level Securityを設定する方法を紹介します。Supabase Authを使うケースが多いとは思いますが、Clerkなどの外部IDaaSと組み合わせるケースに遭遇した際の参考になればと思います。またこの記事は、Supabase Advent Calendar 2024の13日目として投稿しました。
SupabaseでJWTを取得する
Clerkのユーザー情報をSupabaseのRLSで利用するには、まずSupabase側でJWTを取得します。Project settingsからAPI settingsを開き、JWT Settingsにあるシークレットを取得しましょう。
このシークレットは作成後再度取得することができません。再発行する必要がありますので、他で使う可能性も考えると厳重に保管しておきましょう。
ClerkでJWT TemplatesからSupabaseを選ぶ
JWTはClerkで利用します。Clerk側にJWT Templatesという項目がありますので、ここでNew templateを選びましょう。
Supabaseがテンプレートとして表示されますので、選択します。
入力フォームがいくつか表示されます。ここでSigning keyにJWT secretをペーストしましょう。また、AlgorithmがHS256
なのも確認して、保存します。
これで連携準備ができました。
SupabaseのSQL Editorでfunctionを作成
次はSupabaseのRLSで利用する関数を作成します。以下のSQLを実行しましょう。Clerk側のユーザーIDを取得するために利用する・・・と自分の中では理解しています。
create or replace function requesting_user_id()
returns text
language sql stable
as $
select nullif(current_setting('request.jwt.claims', true)::json->>'sub', '')::text;
$;
SQL Editorを使うと、簡単にSQLが実行できるので、Supabaseは便利ですね。
clerk user idを利用するテーブルを作成する
あとはSupabaseで利用するテーブルを作りましょう。この際、Clerkのuser idをtext型で保存できるように設定しておきましょう。
RLSを設定する
最後にテーブルへRLSを設定しましょう。作成した関数でリクエスト時のClerk user idを取得し、read / writeする対象の列にあるclerk_user_id
と一致するかを検証するクエリを設定しています。
readを許可する場合は、次のようなクエリを設定します。
create policy "Read clerk stripe id mapper table"
on "public"."clerk_user_stripe_customer"
as PERMISSIVE
for SELECT
to public
using (
requesting_user_id() = clerk_user_id
);
writeの場合はこうなります。
create policy "write clerk stripe id mapper table"
on "public"."clerk_user_stripe_customer"
as PERMISSIVE
for INSERT
to public
with check (
(requesting_user_id() = clerk_user_id)
);
まとめ
ここまで調べてテストはしたのですが、Clerkのmetadataで十分なデータしかなかったことが判明し、実際には導入しませんでした。そのため、簡単な手順紹介だけに終わっています。とはいえこのような方法でSupabase以外のIDaaSを利用しつつRLSの恩恵を受けることができることがわかったのは、大きな前進だと思います。