Supabase アダプター
リソース
設定
インストール
npm install @supabase/supabase-js @auth/supabase-adapter
環境変数
SUPABASE_URL
SUPABASE_SERVICE_ROLE_KEY
設定
import NextAuth from "next-auth"
import { SupabaseAdapter } from "@auth/supabase-adapter"
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [],
adapter: SupabaseAdapter({
url: process.env.SUPABASE_URL,
secret: process.env.SUPABASE_SERVICE_ROLE_KEY,
}),
})
このアダプターはコミュニティによって開発されており、Supabaseによって公式にメンテナンスまたはサポートされていません。これは、ユーザーとセッションデータを別々のnext_auth
スキーマに保存するためにSupabase Databaseを使用します。Supabase AuthとインターフェースしないスタンドアロンのAuthサーバーであり、そのため異なる機能セットを提供します。
組み込みメールサーバー、電話認証、および多要素認証 (MFA/2FA)などの追加機能を備えた公式にメンテナンスされているAuthサーバーをお探しの場合は、Supabase AuthとNext.js用Authヘルパーを使用してください。
スキーマ
メインのスキーマの説明に従ってデータベースを設定し、以下のSQLスキーマをSupabaseのSQLエディターにコピーします。
または、SQLエディターページでNextAuthクイックスタートカードを選択するか、Supabase CLIでマイグレーションを作成します。
--
-- Name: next_auth; Type: SCHEMA;
--
CREATE SCHEMA next_auth;
GRANT USAGE ON SCHEMA next_auth TO service_role;
GRANT ALL ON SCHEMA next_auth TO postgres;
--
-- Create users table
--
CREATE TABLE IF NOT EXISTS next_auth.users
(
id uuid NOT NULL DEFAULT uuid_generate_v4(),
name text,
email text,
"emailVerified" timestamp with time zone,
image text,
CONSTRAINT users_pkey PRIMARY KEY (id),
CONSTRAINT email_unique UNIQUE (email)
);
GRANT ALL ON TABLE next_auth.users TO postgres;
GRANT ALL ON TABLE next_auth.users TO service_role;
--- uid() function to be used in RLS policies
CREATE FUNCTION next_auth.uid() RETURNS uuid
LANGUAGE sql STABLE
AS $$
select
coalesce(
nullif(current_setting('request.jwt.claim.sub', true), ''),
(nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'sub')
)::uuid
$$;
--
-- Create sessions table
--
CREATE TABLE IF NOT EXISTS next_auth.sessions
(
id uuid NOT NULL DEFAULT uuid_generate_v4(),
expires timestamp with time zone NOT NULL,
"sessionToken" text NOT NULL,
"userId" uuid,
CONSTRAINT sessions_pkey PRIMARY KEY (id),
CONSTRAINT sessionToken_unique UNIQUE ("sessionToken"),
CONSTRAINT "sessions_userId_fkey" FOREIGN KEY ("userId")
REFERENCES next_auth.users (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE CASCADE
);
GRANT ALL ON TABLE next_auth.sessions TO postgres;
GRANT ALL ON TABLE next_auth.sessions TO service_role;
--
-- Create accounts table
--
CREATE TABLE IF NOT EXISTS next_auth.accounts
(
id uuid NOT NULL DEFAULT uuid_generate_v4(),
type text NOT NULL,
provider text NOT NULL,
"providerAccountId" text NOT NULL,
refresh_token text,
access_token text,
expires_at bigint,
token_type text,
scope text,
id_token text,
session_state text,
oauth_token_secret text,
oauth_token text,
"userId" uuid,
CONSTRAINT accounts_pkey PRIMARY KEY (id),
CONSTRAINT provider_unique UNIQUE (provider, "providerAccountId"),
CONSTRAINT "accounts_userId_fkey" FOREIGN KEY ("userId")
REFERENCES next_auth.users (id) MATCH SIMPLE
ON UPDATE NO ACTION
ON DELETE CASCADE
);
GRANT ALL ON TABLE next_auth.accounts TO postgres;
GRANT ALL ON TABLE next_auth.accounts TO service_role;
--
-- Create verification_tokens table
--
CREATE TABLE IF NOT EXISTS next_auth.verification_tokens
(
identifier text,
token text,
expires timestamp with time zone NOT NULL,
CONSTRAINT verification_tokens_pkey PRIMARY KEY (token),
CONSTRAINT token_unique UNIQUE (token),
CONSTRAINT token_identifier_unique UNIQUE (token, identifier)
);
GRANT ALL ON TABLE next_auth.verification_tokens TO postgres;
GRANT ALL ON TABLE next_auth.verification_tokens TO service_role;
Supabase で NextAuth スキーマを公開する
API設定で、「公開されたスキーマ」リストにnext_auth
を追加することにより、サーバーレスAPIを介してnext_auth
スキーマを公開します。
ローカルで開発する場合は、Supabase CLIによって生成されたsupabase
フォルダ内のconfig.toml
ファイルのschemas
配列にnext_auth
を追加します。
高度な使用方法
行レベルセキュリティ (RLS) の有効化
Postgresは、データへのアクセスを制限するための強力な機能である行レベルセキュリティ (RLS)を提供します。
これは、署名されたJWTをSupabaseサーバーレスAPIに送信することによって機能します。これをNextAuthで動作させるには、2つの手順があります。
セッションコールバックで Supabase の access_token
JWT を生成する
JWTに署名するには、jsonwebtoken
パッケージを使用します。
npm install jsonwebtoken
セッションコールバックを使用してSupabaseのaccess_token
を作成し、session
オブジェクトに追加します。
JWTに署名するには、API設定で確認できるSupabase JWTシークレットを使用します。
import NextAuth from "next-auth"
import { SupabaseAdapter } from "@auth/supabase-adapter"
import jwt from "jsonwebtoken"
// For more information on each option (and a full list of options) go to
// https://authjs.dokyumento.jp/reference/core/types#authconfig
export const { handlers, auth, signIn, signOut } = NextAuth({
// https://authjs.dokyumento.jp/getting-started/authentication/oauth
providers: [],
adapter: SupabaseAdapter({
url: process.env.NEXT_PUBLIC_SUPABASE_URL,
secret: process.env.SUPABASE_SERVICE_ROLE_KEY,
}),
callbacks: {
async session({ session, user }) {
const signingSecret = process.env.SUPABASE_JWT_SECRET
if (signingSecret) {
const payload = {
aud: "authenticated",
exp: Math.floor(new Date(session.expires).getTime() / 1000),
sub: user.id,
email: user.email,
role: "authenticated",
}
session.supabaseAccessToken = jwt.sign(payload, signingSecret)
}
return session
},
},
})
Supabase の access_token
JWT をクライアントに挿入する
たとえば、次の公開スキーマがあるとします。
-- Note: This table contains user data. Users should only be able to view and update their own data.
create table users (
-- UUID from next_auth.users
id uuid not null primary key,
name text,
email text,
image text,
constraint "users_id_fkey" foreign key ("id")
references next_auth.users (id) match simple
on update no action
on delete cascade -- if a user is deleted in NextAuth they will also be deleted in our public table.
);
alter table users enable row level security;
create policy "Can view own user data." on users for select using (next_auth.uid() = id);
create policy "Can update own user data." on users for update using (next_auth.uid() = id);
-- This trigger automatically creates a user entry when a new user signs up via NextAuth.
create function public.handle_new_user()
returns trigger as $$
begin
insert into public.users (id, name, email, image)
values (new.id, new.name, new.email, new.image);
return new;
end;
$$ language plpgsql security definer;
create trigger on_auth_user_created
after insert on next_auth.users
for each row execute procedure public.handle_new_user();
supabaseAccessToken
は現在session
オブジェクトで使用可能になり、supabase-jsクライアントに渡すことができます。これは、クライアントサイド、サーバーサイド(APIルート、SSR)、ミドルウェアエッジ関数など、あらゆる環境で機能します!
// Use `useSession()` or `unstable_getServerSession()` to get the NextAuth session.
const { supabaseAccessToken } = session
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
{
global: {
headers: {
Authorization: `Bearer ${supabaseAccessToken}`,
},
},
}
)
// Now you can query with RLS enabled.
const { data, error } = await supabase.from("users").select("*")
TypeScript
Supabase CLIで生成された型をSupabaseクライアントに渡して、強化された型安全性とオートコンプリートを得ることができます。
新しい supabase クライアントオブジェクトの作成
import { createClient } from "@supabase/supabase-js"
import { Database } from "../database.types"
const supabase = createClient<Database>()
supabaseAccessToken
でセッションタイプを拡張する
session
オブジェクトをsupabaseAccessToken
で拡張するには、types/next-auth.d.ts
ファイルでsession
インターフェースを拡張する必要があります。
import NextAuth, { type DefaultSession } from "next-auth"
declare module "next-auth" {
// Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context
interface Session {
// A JWT which can be used as Authorization header with supabase-js for RLS.
supabaseAccessToken?: string
user: {
// The user's postal address
address: string
} & DefaultSession["user"]
}
}