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 官方維護或支援。它使用 Supabase 資料庫將使用者和工作階段資料儲存在一個獨立的 next_auth
結構描述中。它是一個獨立的驗證伺服器,不與 Supabase 驗證介面互動,因此提供不同的功能集。
如果您正在尋找具有額外功能(例如內建電子郵件伺服器、電話驗證,和 多重要素驗證 (MFA / 2FA))的官方維護驗證伺服器,請搭配 Supabase 驗證使用 適用於 Next.js 的驗證輔助程式。
結構描述
依照我們的主要 結構描述中所述設定您的資料庫,方法是在 Supabase SQL 編輯器中複製以下 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 設定中的無伺服器 API 公開 next_auth
結構描述,方法是將 next_auth
新增至「公開的結構描述」清單。
在本地開發時,將 next_auth
新增至由 Supabase CLI產生的 supabase
資料夾中的 config.toml
檔案中的 schemas
陣列。
進階使用
啟用資料列層級安全性 (RLS)
Postgres 提供一項強大的功能,稱為資料列層級安全性 (RLS),可限制對資料的存取。
這透過將已簽署的 JWT 傳送至您的 Supabase 無伺服器 API 來運作。使用 NextAuth 時,需要兩個步驟才能讓此功能運作
在工作階段回呼中產生 Supabase access_token
JWT
若要簽署 JWT,請使用 jsonwebtoken
套件
npm install jsonwebtoken
使用 工作階段回呼建立 Supabase access_token
,並將其附加至 session
物件。
若要簽署 JWT,請使用 Supabase JWT 密碼,該密碼可在API 設定中找到
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.dev.org.tw/reference/core/types#authconfig
export const { handlers, auth, signIn, signOut } = NextAuth({
// https://authjs.dev.org.tw/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
擴展 session
物件,我們需要在 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"]
}
}