🔐

Svelte + Suapbase Auth Google/Github

2024/12/28に公開

💡Tips

SvelteにGithub SignInとGoogle SignInを実装してみた。自分のメモ用に記事を書いておく。

公式は個人のブログを参考に実装した。
https://supabase.com/docs/guides/auth

https://qiita.com/kaho_eng/items/a37ff001ea9eae226183
https://qiita.com/maaaashi/items/05b4226f228a31088550

認証システムのドキュメント

概要

このアプリケーションでは、Supabaseを使用してソーシャルログイン認証を実装しています。現在はGitHub認証を使用していますが、将来的な拡張性を考慮してGoogle認証の実装方法も記録しています。

現在の実装 (GitHub認証)

GitHubログイン実装

async function signInWithGithub() {
    try {
        loading = true;
        error = null;
        const { data, error: signInError } = await supabase.auth.signInWithOAuth({
            provider: "github",
            options: {
                redirectTo: `${window.location.origin}/auth/callback`,
                skipBrowserRedirect: true,
            }
        });

        if (signInError) throw signInError;
        
        if (data?.url) {
            window.location.href = data.url;
        }
    } catch (e) {
        if (e instanceof Error) {
            error = e.message;
        }
        console.error("ログインエラー:", e);
    } finally {
        loading = false;
    }
}

セットアップ手順

  1. Supabaseダッシュボードで「Authentication > Providers」を開く
  2. GitHubプロバイダーを有効化
  3. GitHubのOAuth Appsを作成
    • Settings > Developer settings > OAuth Apps
    • Authorization callback URL: https://[PROJECT_REF].supabase.co/auth/v1/callback

将来の実装参考 (Google認証)

Googleログイン実装

async function signInWithGoogle() {
    try {
        loading = true;
        error = null;
        const { data, error: signInError } = await supabase.auth.signInWithOAuth({
            provider: "google",
            options: {
                redirectTo: `${window.location.origin}/auth/callback`,
                skipBrowserRedirect: true,
                queryParams: {
                    access_type: 'offline',
                    prompt: 'consent'
                }
            }
        });

        if (signInError) throw signInError;
        
        if (data?.url) {
            window.location.href = data.url;
        }
    } catch (e) {
        if (e instanceof Error) {
            error = e.message;
        }
        console.error("ログインエラー:", e);
    } finally {
        loading = false;
    }
}

Google認証セットアップ手順

  1. Supabaseダッシュボードで「Authentication > Providers」を開く
  2. Googleプロバイダーを有効化
  3. Google Cloud Consoleでプロジェクトを作成
  4. OAuth 2.0クライアントIDを作成
    • 承認済みのリダイレクトURI: https://[PROJECT_REF].supabase.co/auth/v1/callback
  5. 取得したクライアントIDとシークレットをSupabaseに設定

コールバック処理

認証後のコールバック処理は以下のファイルで実装されています:
/src/routes/auth/callback/+page.svelte

onMount(async () => {
    try {
        if (!browser) return;

        // 認証状態が安定するまで待機
        await new Promise(resolve => setTimeout(resolve, 1000));

        // セッションの取得
        const { data: { session }, error: sessionError } = await supabase.auth.getSession();
        if (sessionError) throw sessionError;

        if (!session) {
            throw new Error('セッションが見つかりません');
        }

        // ユーザー情報の取得と更新
        const { data: { user }, error: userError } = await supabase.auth.getUser();
        if (userError) throw userError;

        if (user) {
            // プロバイダー情報の更新
            const currentProviders = user.app_metadata?.providers || [];
            if (!currentProviders.includes(session.provider_token ? 'github' : 'google')) {
                await supabase.auth.updateUser({
                    data: {
                        providers: [...currentProviders, session.provider_token ? 'github' : 'google']
                    }
                });
            }
        }

        // ダッシュボードへリダイレクト
        await goto('/dashboard');
    } catch (e) {
        console.error('認証エラー:', e);
        await goto('/');
    }
});

注意点

  1. 複数のプロバイダーを同時に使用する場合、セッション管理に注意が必要
  2. リダイレクトURLは環境に応じて適切に設定
  3. エラーハンドリングを適切に実装
  4. ユーザーメタデータの更新は慎重に行う

トラブルシューティング

  • The message port closed before a response was receivedエラーが発生した場合:
    • skipBrowserRedirect: trueの設定を確認
    • リダイレクトの処理を手動で行う
    • コールバックページでの待機時間を調整

セキュリティ考慮事項

  1. 環境変数による認証情報の管理
  2. 適切なスコープの設定
  3. セッショントークンの安全な管理
  4. CORS設定の確認

Discussion