

- Share On
目次
Next.jsでWebサイトを構築し、認証機能の実装を検討している開発者の方々にとって、SupabaseAuthは非常に魅力的な選択肢です。SupabaseAuthを利用することで、メールアドレスとパスワード、各種ソーシャルアカウント連携など、多様な認証方法を簡単に組み込むことができ、ユーザー管理の負担を軽減できます。
本記事では、Supabaseの基本的な概念から、Next.jsとの連携、実際の認証機能の実装、そしてセキュリティに関する考慮事項を解説します。
Supabaseの基本
SupabaseはFirebaseのオープンソース代替を謳うBaaS(Backend as a Service)プラットフォームです。
データベース、認証、ストレージ、リアルタイム機能、関数などアプリケーションのバックエンドに必要な主要機能を提供しています。
特にPostgreSQLをベースとしているためリレーショナルデータベースの知識を活かしつつ手軽にバックエンドを構築できる点が大きな特徴です。またAPIが自動生成されるためフロントエンド開発に集中しやすい環境が整っています。
Supabaseの概要
Supabaseは、開発者がPostgreSQLデータベース、認証、ストレージ、リアルタイム機能、Functionsなど、幅広いバックエンド機能を迅速に利用できるオープンソースプラットフォームです。
FirebaseのようなBaaSと比較されることが多く、特にデータベースにPostgreSQLを採用している点が異なります。これにより、従来のSQLに慣れている開発者にとっては学習コストが低く、リレーショナルデータベースの柔軟性を活用したデータ管理が可能です。
Supabaseを利用することで、バックエンドの構築にかかる時間を大幅に短縮し、開発者はアプリケーションのフロントエンドやビジネスロジックに集中できるようになります。
Supabase Authの機能
SupabaseAuthはSupabaseが提供する認証およびユーザー管理サービスでありアプリケーションに簡単かつセキュアなユーザー認証機能を提供します。
メールアドレスとパスワードによる認証はもちろんのことマジックリンクワンタイムパスワード(OTP)に加えGoogleGitHubFacebookAppleなどの人気のソーシャルログイン(OAuthプロバイダー)にも対応しています。
ユーザーデータはPostgreSQLのauth.users
テーブルに安全に保存されログイン管理も可能です。さらにJSONWebTokens(JWT)を用いたセキュアな認証情報の交換やロールベースのアクセス制御(RBAC)により堅牢なセキュリティモデルを実現しています。
実務では、supabase auth のサインイン/サインアップ、OAuth連携、セッション管理(getUser / getSession)、Webフック(Auth hooks)まで一貫して扱える点が大きな利点です。
セキュリティの考慮事項
Supabaseを利用する上で、セキュリティは非常に重要な側面です。データベースへのアクセス制御を誤ると、意図しない情報漏洩やデータ改ざんのリスクが生じる可能性があります。
Supabaseでは、PostgreSQLのRow Level Security (RLS) を活用することで、行単位での詳細なアクセス制御が可能です。RLSを有効にしないと、公開されているAPIキー (anonキー) を使って誰でもCRUD操作 (作成・読み取り・更新・削除) ができてしまうため、必ず有効化し、適切なポリシーを設定する必要があります。
また、Supabaseには、RLSをバイパスできる「サービスキー」が存在しますが、これはフロントエンドに公開すべきではありません。サービスキーはバックエンド側で環境変数として安全に保管し、管理作業にのみ使用することがベストプラクティスとされています。これらのセキュリティ対策を講じることで、アプリケーションの安全性を高めることができます。
Supabaseプロジェクトの準備
Next.jsアプリケーションにSupabaseを統合するためには、まずSupabaseプロジェクトを適切に準備する必要があります。これには、Supabaseアカウントの作成から新規プロジェクトの立ち上げ、そしてNext.jsプロジェクトとの連携設定までの一連のプロセスが含まれます。
これらのステップを順序通りに進めることで、円滑な開発環境を構築できます。
アカウントとプロジェクトの作成
Supabaseを利用するには、まずSupabaseの公式サイトにアクセスし、アカウントを作成する必要があります。
GitHubアカウントやメールアドレスとパスワードを使用して登録が可能です。パスワードは、大文字・小文字の英字、数字、記号を含む8文字以上という制約があるため注意しましょう。
アカウント作成後、ダッシュボードから新しいプロジェクトを作成します。この際、プロジェクト名、データベースのパスワード、そしてリージョンを設定します。
開発用と本番用で異なるプロジェクトを作成することが推奨されています。例えば、my-app-devとmy-app-prodのように設定すると良いでしょう。
プロジェクト作成が完了すると、APIキーとURLが発行され、これらは後ほどNext.jsプロジェクトからSupabaseに接続するために必要となります。
運用を見据えて、開発・ステージング・本番を分離し、それぞれのanon key / service roleを環境変数で切り替える構成をおすすめします。
Next.jsとの連携
Next.jsプロジェクトとSupabaseを連携させるには、まずNext.jsプロジェクトを作成し、SupabaseクライアントSDKをインストールします。
ターミナルで以下のコマンドを実行してNext.jsプロジェクトを作成し、SupabaseSDKをインストールします。
npx create-next-app nextjs-supabase-auth
cd nextjs-supabase-auth
npm install @supabase/supabase-js @supabase/ssr
次に、Supabaseプロジェクトから取得したAPI URLと公開anonキーを環境変数として設定します。プロジェクトのルートディレクトリに.env.local
ファイルを作成し、以下の形式で記述します。
NEXT_PUBLIC_SUPABASE_URL=YOUR_SUPABASE_URL
NEXT_PUBLIC_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY
これらの環境変数を基に、Supabaseクライアントを初期化するファイルをlib/supabase.ts
のようなパスで作成します。
サーバーサイドレンダリング(SSR)やクライアントサイドでの利用を考慮し、適切にクライアントを生成することが重要です。
// lib/supabase.ts(App Router対応の推奨パターン)
import { createBrowserClient, createServerClient } from '@supabase/ssr'
import type { Database } from '@/types/supabase'
const url = process.env.NEXT_PUBLIC_SUPABASE_URL!
const key = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
export const supabaseBrowser = () =>
createBrowserClient<Database>(url, key)
export const supabaseServer = (cookies: any) =>
createServerClient<Database>(url, key, { cookies })
App Routerでのセッション維持/SSRまで考えると、@supabase/ssrのcreateBrowserClient / createServerClientによる二系統のクライアント分離が安全です(supabase auth のセッションCookieを適切に扱えるため)。
この設定により、Next.jsアプリケーションからSupabaseの認証機能やデータベースにアクセスできるようになります。
認証機能の実装
SupabaseAuthを活用することで、Next.jsアプリケーションに多様な認証機能を効率的に実装できます。ここでは、基本的なユーザー登録から、利便性の高いGoogle認証、その他の認証方法について解説します。
これらの機能を組み合わせることで、ユーザーにとって使いやすく、セキュアな認証システムを構築することが可能です。
ユーザー登録機能
SupabaseAuthでユーザー登録機能を実装するには、メールアドレスとパスワードによる認証が最も一般的です。
SupabaseのクライアントSDKを使用し、supabase.auth.signUp()
メソッドを呼び出すことで、簡単にユーザー登録が可能です。例えば、以下のようなコードでサインアップ処理を実装できます。
// app/auth/signup/page.tsx
'use client'
import { useState, FormEvent } from 'react'
import { supabaseBrowser } from '@/lib/supabase'
export default function SignUp() {
const supabase = supabaseBrowser()
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [isLoading, setIsLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const handleSignUp = async (e: FormEvent) => {
e.preventDefault()
setIsLoading(true)
setError(null)
const { error } = await supabase.auth.signUp({ email, password })
setIsLoading(false)
if (error) setError(error.message)
else alert('サインアップが完了しました。確認メールをご覧ください。')
}
return (
<form onSubmit={handleSignUp} className="space-y-3">
<input type="email" value={email} onChange={(e) => setEmail(e.target.value)} required className="border p-2 w-full" placeholder="メールアドレス" />
<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} required className="border p-2 w-full" placeholder="パスワード" />
<button type="submit" disabled={isLoading} className="bg-blue-600 text-white px-4 py-2 rounded">
{isLoading ? '登録中…' : '登録'}
</button>
{error && <p className="text-red-600">{error}</p>}
</form>
)
}
ユーザーが登録すると、指定したメールアドレスに認証メールが送信されます。SupabaseのダッシュボードでEmailプロバイダを有効にし、メールテンプレートをカスタマイズすることで、よりユーザーフレンドリーな登録プロセスを提供できます。
また、AuthHookを利用することで、サインアップ時にusers
テーブルへユーザーデータを自動的に保存するなどの追加処理を実装することも可能です。
Google認証の実装
Google認証を実装することで、ユーザーは既存のGoogleアカウントを利用して手軽にサインインできるようになります。SupabaseAuthはGoogle認証をサポートしており、ウェブアプリケーション、Android、Chrome拡張機能に対応しています。
実装の主な手順は以下の通りです。
GoogleCloudプロジェクトの設定
GoogleCloudConsoleで新しいプロジェクトを作成し、OAuth同意画面を設定します。ユーザータイプを「外部」に設定し、アプリケーション名、ユーザーサポートメール、デベロッパー連絡先メール、承認済みドメイン(Supabaseプロジェクトのドメインを含む)を入力します。OAuthクライアントIDの発行
認証情報からOAuthクライアントIDを作成します。アプリケーションの種類を「ウェブアプリケーション」とし、承認済みJavaScript生成元にhttp://localhost:3000
(開発環境)や本番環境のURL(例\:VercelのURL)を追加します。承認済みリダイレクトURIには、Supabaseダッシュボードの「Authentication」→「CONFIGURATION」→「SignIn/Providers」→「Google」で表示される「CallbackURL(forOAuth)」をコピーして貼り付けます。これにより、クライアントIDとクライアントシークレットが発行されるので、これらを控えておきます。Supabase側の設定
Supabaseダッシュボードの「Authentication」→「SignIn/Up」→「AuthProviders」からGoogleを選択し、「EnableSigninwithGoogle」をオンにします。取得したクライアントIDとクライアントシークレットをSupabaseの該当フィールドに貼り付け、本番ドメインや追加のリダイレクトURLを設定し保存します。Next.jsコードの実装
Next.jsアプリケーション内で、supabase.auth.signInWithOAuth()
メソッドを使用してGoogle認証フローを開始します。
// app/auth/google/page.tsx
'use client'
import { supabaseBrowser } from '@/lib/supabase'
export default function GoogleSignIn() {
const supabase = supabaseBrowser()
const handleGoogleSignIn = async () => {
const { error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: { redirectTo: `${window.location.origin}/auth/callback` },
})
if (error) console.error('Google認証エラー:', error.message)
}
return (
<button onClick={handleGoogleSignIn} className="bg-red-500 text-white px-4 py-2 rounded">
Sign in with Google
</button>
)
}
併せて、コールバックページでセッションを確認します。
// app/auth/callback/page.tsx
import { cookies } from 'next/headers'
import { supabaseServer } from '@/lib/supabase'
export default async function Callback() {
const supabase = supabaseServer(cookies)
const { data: { user } } = await supabase.auth.getUser()
return <p>{user ? `ログイン中:${user.email}` : 'ユーザー情報を取得できませんでした。'}</p>
}
認証が成功すると、指定されたリダイレクトURLに遷移し、ユーザー情報が取得できるようになります。
その他の認証方法
SupabaseAuthは、メールアドレスとパスワード、Google認証以外にも、多様な認証方法をサポートしています。これには、GitHub、Facebook、Apple、Discord、Slackなどの一般的なソーシャルプロバイダーが含まれます。
また、電話番号認証やマジックリンク(パスワードなしでメールリンク経由でログイン)、ワンタイムパスワード(OTP)なども利用可能です。これらの認証方法を実装する際も、基本的なフローはGoogle認証と同様に、各プロバイダー側の設定とSupabaseのダッシュボードでの有効化、そしてSupabaseクライアントSDKの適切なメソッド呼び出しで行います。
例えば、マジックリンク認証ではsupabase.auth.signInWithOtp({ email })
を使用します。
プロジェクトの要件やターゲットユーザーに合わせて、最適な認証方法を選択し、導入することで、ユーザーの利便性を高めながら安全なアクセスを提供することが可能です。
通常のログイン/ログアウトは次のように実装できます。
// app/auth/login/page.tsx
'use client'
import { useState } from 'react'
import { supabaseBrowser } from '@/lib/supabase'
export default function Login() {
const supabase = supabaseBrowser()
const [email, setEmail] = useState(''); const [password, setPassword] = useState('')
const [error, setError] = useState<string | null>(null)
const signIn = async () => {
const { error } = await supabase.auth.signInWithPassword({ email, password })
if (error) setError(error.message)
}
const signOut = async () => { await supabase.auth.signOut() }
return (
<div className="space-x-2">
<input value={email} onChange={(e)=>setEmail(e.target.value)} placeholder="email" className="border p-2" />
<input type="password" value={password} onChange={(e)=>setPassword(e.target.value)} placeholder="password" className="border p-2" />
<button onClick={signIn} className="bg-green-600 text-white px-3 py-2 rounded">ログイン</button>
<button onClick={signOut} className="bg-gray-600 text-white px-3 py-2 rounded">ログアウト</button>
{error && <p className="text-red-600">{error}</p>}
</div>
)
}
データセキュリティとテーブル管理
認証機能の実装だけでなく、Supabaseで構築するアプリケーションにおいては、データのセキュリティとテーブル管理が非常に重要です。特に、RowLevelSecurity(RLS)の活用は、データへのアクセスを細かく制御し、不正アクセスから保護するために不可欠な機能です。
ここでは、RLSの適用方法から、テーブル権限の設定、そしてユーザーテーブルとの連携について詳しく解説します。
Row Level Security (RLS) の活用
RowLevelSecurity(RLS)は、PostgreSQLの強力な機能であり、Supabaseのデータセキュリティの中核を担います。
RLSを有効にすると、データベースの各行に対して個別にアクセスルールを定義できるようになり、認証されたユーザーが必要なデータのみにアクセスできるような、きめ細やかな権限管理を実現します。
RLSを有効にするには、SQLエディタで以下のコマンドを実行します。
ALTER TABLE "your_table_name" ENABLE ROW LEVEL SECURITY;
RLSを有効にしただけでは、公開anonキーからのデータアクセスがすべて拒否されるため、次に「ポリシー」を作成する必要があります。
ポリシーは、データへのアクセスを許可する条件を定義するSQLルールであり、例えば「ユーザーは自分の投稿のみを閲覧できる」といった具体的な要件を実装できます。auth.uid()のようなSupabaseが提供するヘルパー関数を利用することで、現在の認証済みユーザーのIDに基づいたポリシーを簡単に記述できます。
以下は、ユーザーが自身の投稿のみを閲覧できるようにするポリシーの例です。
CREATE POLICY "Individuals can view their own posts."
ON posts
FOR SELECT
USING (auth.uid() = user_id);
このようにRLSとポリシーを組み合わせることで、フロントエンドから直接データベースにアクセスする場合でも、高いセキュリティレベルを維持することが可能です。
テーブル権限の設定
Supabaseでは、デフォルトでテーブルを作成すると、公開されているanon
キー(クライアントキー)を使って誰でもCRUD操作が行える設定になっている場合があります。これは開発を容易にする一方で、悪意のあるユーザーによるデータ改ざんや削除のリスクがあるため、セキュリティ対策としてテーブル権限を適切に変更する必要があります。
テーブル単位のアクセス制御を行うには、まず現在のロールと権限を確認します。SupabaseのSQLEditorで以下のクエリを実行することで確認できます。
SELECT grantee, table_name, privilege_type
FROM information_schema.role_table_grants
WHERE table_schema = 'public'
ORDER BY grantee, table_name, privilege_type;
この結果にanon
が含まれている場合、そのテーブルは誰でもアクセス可能です。認証済みのユーザーのみがアクセスできるように制限するには、anon
ロールからすべての権限を剥奪するSQLを実行します。
REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA public FROM anon;
これにより、認証されていないユーザーからのテーブルへのアクセスが制限されます。
個々のテーブルに対して、より詳細な権限設定を行いたい場合は、GRANT
文を使用して特定のロールに特定の操作(SELECT,INSERT,UPDATE,DELETEなど)を許可することができます。
例えば、認証済みユーザーに対してのみデータ挿入を許可したい場合は、WITH CHECK
句を組み合わせて、挿入されるデータのユーザーIDが認証ユーザーIDと一致するかどうかを検証するポリシーを設定することで、他のユーザーのデータを誤って登録することを防げます。
ユーザーテーブルと連携
SupabaseAuthでユーザーが登録されると、その情報は自動的にPostgreSQLのauth.users
テーブルに保存されます。
しかし、アプリケーションでユーザーのプロフィール情報(例:名前、アバターURLなど)を管理する場合、別途カスタムのprofiles
テーブルなどを作成し、auth.users
テーブルと連携させることが一般的です。この連携は、主に外部キー制約とトリガー(AuthHook)を利用して行われます。
例えば、ユーザーが新規登録された際に、auth.users
テーブルのid
を主キーとして、カスタムのprofiles
テーブルにも対応するレコードを自動で作成するトリガーを設定できます。この際、サインアップ時にoptions
としてメタデータを渡すことで、AuthHook内でfull_name
やavatar_url
といった「Authに登録するときには不要だが、データベースには登録したい情報」を扱えるようになり、ユーザー情報の登録と紐付けを効率的に行うことが可能です。
このような連携により、認証システムとユーザーデータ管理を一貫して行うことができ、アプリケーションの機能拡張やデータ操作が容易になります。
-- 例:profilesをauth.usersに追随させるトリガー(publicスキーマ想定)
create table if not exists public.profiles (
id uuid primary key references auth.users(id) on delete cascade,
full_name text,
avatar_url text,
created_at timestamp with time zone default now()
);
create or replace function public.handle_new_user()
returns trigger language plpgsql security definer set search_path = public as $$
begin
insert into public.profiles (id) values (new.id);
return new;
end;
$$;
drop trigger if exists on_auth_user_created on auth.users;
create trigger on_auth_user_created
after insert on auth.users
for each row execute function public.handle_new_user();
ローカル開発環境の構築
Supabaseを使用したNext.jsアプリケーションの開発では、本番環境だけでなく、ローカルでの開発環境を効率的に構築することが重要です。
Supabase CLIを活用することで、Dockerを使ったSupabaseスタックのローカル起動や、データベースのマイグレーション管理など、開発プロセスをスムーズに進めることが可能になります。
Supabase CLIの利用
SupabaseCLIは、Supabaseプロジェクトをローカルで管理し、開発を加速させるための強力なコマンドラインツールです。これにより、リモートのSupabaseプロジェクトを操作するだけでなく、ローカルマシン上でSupabaseの全スタック(Postgresデータベース、Auth、Storageなど)をDockerコンテナとして起動できるようになります。
SupabaseCLIをインストールするには、brew install supabase/tap/supabase
(macOSの場合)やnpm i supabase --save-dev
などのコマンドが利用できます。インストール後、supabase login
コマンドでSupabaseアカウントにログインし、アクセストークンを貼り付けることで、CLIとSupabaseプロジェクトを連携させます。
その後、supabase init
コマンドで新しいSupabaseプロジェクトを初期化し、supabase/config.toml
などの設定ファイルが生成されます。これにより、ローカルでの開発準備が整います。
型安全に進める場合は、CLIでDBスキーマから型を自動生成してNext.jsに取り込むと便利です。
例:supabase gen types typescript --linked > src/types/supabase.ts
ローカル環境の起動と確認
Supabase CLIを利用してローカル開発環境を起動するには、supabase start
コマンドを実行します。初回起動時には、必要なDockerイメージがダウンロードされるため、時間がかかる場合があります。
起動が完了すると、supabase status
コマンドでローカルのSupabaseインスタンスのURLやAPI情報が表示されます。通常、Supabase Studioのローカル版にはhttp://localhost:54323
でアクセスでき、データベースや認証の状態を確認できます。
これにより、実際のデプロイ前にローカル環境でデータベーススキーマの変更、認証フローのテスト、機能の検証などを安心して行うことが可能になります。
加えて、supabase db commit
コマンドでデータベースの変更をマイグレーションファイルとして保存したり、supabase db reset
でデータベースをリセットして初期状態に戻したりすることもでき、開発効率が大幅に向上します。
まとめ
本記事では、Next.jsプロジェクトにSupabase Authを統合し、認証機能を実装する方法について解説しました。Supabaseの基本概念から、プロジェクトの準備、実際のユーザー登録やGoogle認証の実装、さらにはデータセキュリティとテーブル管理、そしてローカル開発環境の構築まで説明をいたしました。
株式会社デパートでは、システム開発に関して一貫して対応可能です。 セキュアでスケーラブルな認証システムや、その他モダン開発などの無料相談も承っておりますので、ぜひお気軽にご相談ください。
Contact
制作のご依頼やサービスに関するお問い合わせ、
まだ案件化していないご相談など、
お気軽にお問い合わせください。
- この記事をシェア