Supabase Authでメール認証ログインを実装する 管理ページの保護に使える
この記事の要点
Supabase Authのメール+パスワード認証を使って、個人開発の管理ページを保護する実装方法を解説する。ログインフォーム・セッション管理・保護ページの作り方をAstroでのコード例とともに示す。
結論
Supabase Authのメール認証は、signInWithPassword()とgetSession()の2つの関数を覚えるだけで基本的な実装が完成する。管理ページをシンプルなパスワード保護にしたいなら、環境変数とBasic認証で十分なケースもあるが、Supabase Authを使うと将来的な機能拡張(複数管理者・ロール管理等)が容易になる。
Supabase Authの設定
1. Authプロバイダーの確認
Supabaseダッシュボード → Authentication → Providers で「Email」が有効になっていることを確認する(デフォルトで有効)。
2. メール確認の設定(管理者用途は無効推奨)
Authentication → Email Templates でメール確認の設定が確認できる。管理者1人のみが使うサイトでは、新規登録時のメール確認を無効にすると手間が減る。
Authentication → Settings → 「Confirm email」をオフにすると、登録直後から使える状態になる。
3. 管理者アカウントの作成
ダッシュボード → Authentication → Users → 「Invite user」または「Add user」で管理者アカウントを直接作成できる。
SupabaseクライアントとAuthの初期化
src/lib/supabase.tsでクライアントを設定する。
import { createClient } from '@supabase/supabase-js';
const supabaseUrl = import.meta.env.PUBLIC_SUPABASE_URL;
const supabaseAnonKey = import.meta.env.PUBLIC_SUPABASE_ANON_KEY;
export const supabase = createClient(supabaseUrl, supabaseAnonKey, {
auth: {
// セッションをlocalStorageに保持(ブラウザリロード後も維持)
persistSession: true,
autoRefreshToken: true,
},
});
ログインフォームの実装
src/pages/login.astroを作成する。
---
// ビルド時のサーバーサイドでは認証できないためフロントエンドで処理
---
<html lang="ja">
<body>
<form id="login-form">
<h1>管理者ログイン</h1>
<div>
<label>メールアドレス</label>
<input type="email" id="email" required />
</div>
<div>
<label>パスワード</label>
<input type="password" id="password" required />
</div>
<button type="submit">ログイン</button>
<p id="error-msg" hidden style="color: red;"></p>
</form>
<script>
import { supabase } from '../lib/supabase';
// すでにログイン済みなら管理画面にリダイレクト
const { data: { session } } = await supabase.auth.getSession();
if (session) window.location.href = '/admin/';
document.getElementById('login-form').addEventListener('submit', async (e) => {
e.preventDefault();
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
const { error } = await supabase.auth.signInWithPassword({ email, password });
if (error) {
const msg = document.getElementById('error-msg');
msg.textContent = 'ログインに失敗しました。メールアドレスとパスワードを確認してください。';
msg.hidden = false;
} else {
window.location.href = '/admin/';
}
});
</script>
</body>
</html>
保護ページの実装
管理ページに認証チェックを追加する。src/pages/admin/index.astroを作成する。
---
// このページは静的生成(サーバーサイドではセッション確認できない)
---
<html lang="ja">
<body>
<!-- ログインしていない場合は何も表示しない(JSが確認後に表示) -->
<div id="admin-content" hidden>
<h1>管理ダッシュボード</h1>
<!-- 管理コンテンツ -->
</div>
<script>
import { supabase } from '../../lib/supabase';
// セッション確認
const { data: { session } } = await supabase.auth.getSession();
if (!session) {
// 未認証ならログインページにリダイレクト
window.location.href = '/login';
} else {
// 認証済みならコンテンツを表示
document.getElementById('admin-content').hidden = false;
}
</script>
</body>
</html>
注意点:静的生成されたページでは、ページのHTMLが一瞬表示される可能性がある。重要な機密コンテンツは、JavaScriptでセッション確認後に動的にロードする設計にすることを推奨する。
ログアウトの実装
import { supabase } from '../lib/supabase';
async function logout() {
await supabase.auth.signOut();
window.location.href = '/login';
}
document.getElementById('logout-btn').addEventListener('click', logout);
セッションの確認とユーザー情報の取得
// 現在のセッションを取得
const { data: { session } } = await supabase.auth.getSession();
// セッションがある場合はユーザー情報を取得
if (session) {
const user = session.user;
console.log('ログイン中のユーザー:', user.email);
console.log('ユーザーID:', user.id);
}
// セッションの変化を監視(ログイン・ログアウトの検知)
supabase.auth.onAuthStateChange((event, session) => {
if (event === 'SIGNED_OUT') {
window.location.href = '/login';
}
});
AstroのSSRモードでのより確実な保護
AstroをSSRモード(output: 'server')で動かすと、ページのリクエスト時にサーバーサイドでセッションを確認できる。静的サイトよりも安全に保護ページを作れる。
---
// SSRモードの場合、サーバーサイドでセッション確認が可能
import { createServerClient } from '@supabase/ssr';
const supabase = createServerClient(
import.meta.env.SUPABASE_URL,
import.meta.env.SUPABASE_ANON_KEY,
{
cookies: {
get: (key) => Astro.cookies.get(key)?.value,
set: (key, value, options) => Astro.cookies.set(key, value, options),
remove: (key) => Astro.cookies.delete(key),
},
}
);
const { data: { session } } = await supabase.auth.getSession();
if (!session) {
return Astro.redirect('/login');
}
---
<h1>管理画面(認証済みのみ表示)</h1>
SSRモードではHTMLが生成される前にリダイレクトできるため、コンテンツが一瞬見える問題がなくなる。
Supabaseの基本セットアップはSupabaseの始め方を、RLSの設定はSupabaseの行レベルセキュリティ(RLS)入門で解説している。
まとめ
Supabase Authのメール認証は、signInWithPassword()でログインしてgetSession()でセッション確認する、この2つが基本だ。静的生成のAstroサイトでは、JavaScriptでセッション確認後にコンテンツを表示するパターンで管理ページを保護できる。より確実な保護が必要な場合はSSRモードへの切り替えを検討する。
よくある質問
Supabase Authは無料で使えますか
Freeプランで月5万人のMAU(月間アクティブユーザー)まで無料です。個人開発の管理ページなら自分1人しか使わないため、無料枠で十分です。
Supabase AuthはSNSログイン(GoogleやGitHub)にも対応していますか
対応しています。Google・GitHub・Twitter・Facebook・Apple等のOAuthプロバイダーを設定できます。各プロバイダーでOAuthアプリを作成してクライアントIDとシークレットをSupabaseに設定するだけで使えます。
Astroの静的サイトでログイン状態の保護はどう実装しますか
AstroのサーバーサイドレンダリングまたはクライアントサイドのJavaScriptでセッションを確認して、未認証ならログインページにリダイレクトする方法で実装します。静的ページの場合、表示した後にJavaScriptでセッション確認してリダイレクトします。
パスワードを忘れたときのリセット機能も実装できますか
Supabase Authは標準でパスワードリセット機能を持っています。resetPasswordForEmail()を呼び出すと、リセットメールが自動送信されます。Resendとの連携でカスタムドメインからメールを送ることもできます。