0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GitHub認証 ソーシャルログイン (Next.js Supabase ローカル開発環境用)

Last updated at Posted at 2024-12-27

このコードのリポジトリ

masakinihirota/nextjs_supabase

GitHub認証の動作確認済み

目的

Bolt.newというWebサービスでGitHub認証機能を作ってもらいましたが、どのように動いているのか実際のコードを確認します。

この記事では、SupabaseでGitHub認証を確認します。ローカル環境で動作させます。

前提知識

  • Next.js 15
  • Supabase (サーバー環境)
  • Supabase (ローカル環境)
  • TypeScript
  • VSCode
  • GitHub

Supabase (ローカル環境) ダッシュボード

Next.js インストール

npx create-next-app@latest --typescript --tailwind --eslint

[app name]
√ Would you like your code inside a `src/` directory? ... No / [Yes]
√ Would you like to use App Router? (recommended) ... No / [Yes]
√ Would you like to use Turbopack for `next dev`? ... No / [Yes]
√ Would you like to customize the import alias (`@/*` by default)? ... No / [Yes]
√ What import alias would you like configured? ... @/*

Next.jsの環境ファイル

※注意

環境変数のファイルは .env というファイル名にしてください。

Next.jsの環境変数設定に関するトラブルシューティング `.env.local` ファイルでは環境変数を読み込んでくれませんでした。(Windows10環境)

.env.localの設定は正しいと信じ込み、他の場所を色々試しましたがundefinedとなり、読み込んでくれませんでした。以前あったトラブルを思い出し、.envとファイル名を変更したら読み込んでくれました。

ローカル環境のSupabase インストール

npm install @supabase/supabase-js @supabase/auth-helpers-nextjs react-icons

supabase init
supabase start
supabase status

Supabaseの環境変数

         API URL: http://127.0.0.1:54321
     GraphQL URL: http://127.0.0.1:54321/graphql/v1
  S3 Storage URL: http://127.0.0.1:54321/storage/v1/s3
          DB URL: postgresql://postgres:postgres@127.0.0.1:54322/postgres
      Studio URL: http://127.0.0.1:54323
    Inbucket URL: http://127.0.0.1:54324
      JWT secret: super-secret-jwt-token-with-at-least-32-characters-long
        anon key: ey*****I0
service_role key: ey*****U
   S3 Access Key: 62*****3c
   S3 Secret Key: 85*****07
       S3 Region: local

Next.js アプリの環境変数

Next.js、GitHub認証の環境変数

GitHubの環境変数 GITHUB_CLIENT_ID と GITHUB_SECRET の取得方法は👇️を御覧ください。

Next.js + Supabase アプリでサーバーやローカル開発環境で、認証に必要な Client ID と Client secrets の取得。(Slack、Google、GitHub) #OAuth - Qiita

GitHub認証 ローカルで動かす OAuth-practice #localhost - Qiita

touch .env

.envファイルに以下を記述します。

.env
# 環境変数
# Next.js 15
# Supabase ローカルローカル環境
GITHUB_REDIRECT_URI="http://127.0.0.1:54321/auth/v1/callback"
GITHUB_CLIENT_ID="Ox***"
GITHUB_SECRET="e3***"

NEXT_PUBLIC_SITE_URL="http://localhost:3000"
NEXT_PUBLIC_SUPABASE_URL="http://127.0.0.1:54321"
NEXT_PUBLIC_SUPABASE_ANON_KEY="ey***"

認証機能の実装: Supabase Authを用いた ソーシャルログイン (GitHub認証)

Next.js Supabase でのソーシャルログイン (Github認証) を作成します。

SupabaseでのGitHub認証の有効化

Supabaseの設定ファイルに追記します。

config.toml
...
[auth.external.github]
enabled = true
client_id = "env(GITHUB_CLIENT_ID)"
secret = "env(GITHUB_SECRET)"
# Overrides the default auth redirectUrl.
redirect_uri = ""

Supabaseがエラーで起動しない場合

supabase_vector_[アプリ名] container is not ready: unhealthy エラー対処方法 Supabaseローカル開発環境 #Supabase - Qiita

config.toml
...
[analytics]
enabled = false
port = 54327
# Configure one of the supported backends: `postgres`, `bigquery`.
backend = "postgres"

👆️設定ファイルの一部 [analytics] を無効化します。

Next.js での GitHub認証コードの実装

GitHub認証に必要な最低限のファイルツリー

./src
├── app
│   ├── auth
│   │   └── callback
│   │       └── route.ts
│   ├── layout.tsx
│   └── page.tsx
├── components
│   └── auth
│       └── social-login-buttons.tsx
└── lib
    └── supabase.ts

./supabae
└── config.toml

supabaseフォルダは supabase init コマンドで自動で出来ます。

src\app\layout.tsx

src\app\layout.tsx
import './globals.css';
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';

const inter = Inter({ subsets: ['latin'] });

export const metadata: Metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
  }) {
  return (
    <html lang="ja">
      <body className={inter.className}>{children}</body>
    </html>
  );
}

src\app\page.tsx

src\app\page.tsx
import { SocialLoginButtons } from '@/components/auth/social-login-buttons';

export default function Home() {
  return (
    <div className="min-h-screen flex items-center justify-center bg-background">
      <h1 className="text-2xl font-bold text-center text-foreground">
        ソーシャルログイン
      </h1>
      <SocialLoginButtons />
    </div>
  );
}

src\components\auth\social-login-buttons.tsx

src\components\auth\social-login-buttons.tsx
'use client';

import { supabase } from '@/lib/supabase';

import { FcGoogle } from 'react-icons/fc';
import { FaGithub } from 'react-icons/fa';

export function SocialLoginButtons() {
  // 確認
  console.log('SocialLoginButtons');
  const handleGithubLogin = async () => {
    // 確認
    console.log('handleGithubLogin');
    await supabase.auth.signInWithOAuth({
      provider: 'github',
      options: {
        // サーバー側でのリダイレクトURLを指定
        // redirectTo: `${window.location.origin}/auth/callback`,
        // ローカル環境でのリダイレクトURLを指定
        redirectTo: 'http://192.168.1.2:3000/auth/callback',
      },
    });
  };

  const handleGoogleLogin = async () => {
    await supabase.auth.signInWithOAuth({
      provider: 'google',
      options: {
        // サーバー側でのリダイレクトURLを指定
        // redirectTo: `${window.location.origin}/auth/callback`,
        // ローカル環境でのリダイレクトURLを指定
        redirectTo: 'http://192.168.1.2:3000/auth/callback',

      },
    });
  };

  return (
    <div className="flex flex-col gap-4 w-full max-w-sm">
      <button
        onClick={handleGithubLogin}
      >
        <FaGithub className="w-5 h-5" />
        GitHubでログイン
      </button>
      <button
        onClick={handleGoogleLogin}
      >
        <FcGoogle className="w-5 h-5" />
        Googleでログイン
      </button>
    </div>
  );
}

src\lib\supabase.ts

src\lib\supabase.ts
import { createClient } from '@supabase/supabase-js';

if (!process.env.NEXT_PUBLIC_SUPABASE_URL) {
  throw new Error('Missing env.NEXT_PUBLIC_SUPABASE_URL');
}
if (!process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY) {
  throw new Error('Missing env.NEXT_PUBLIC_SUPABASE_ANON_KEY');
}

export const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
);

src\app\auth\callback\route.ts

src\app\auth\callback\route.ts
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
import { NextResponse } from 'next/server';

export async function GET(request: Request) {
  const requestUrl = new URL(request.url);
  const code = requestUrl.searchParams.get('code');

  if (code) {
    const supabase = createRouteHandlerClient({ cookies });
    await supabase.auth.exchangeCodeForSession(code);
  }

  return NextResponse.redirect(new URL('/', requestUrl.origin));
}

以上でコードは終了です。

Next.jsを立ち上げ、
Supabaseを立ち上げ
ログインボタンを押せば、Supabaseのauth.usersテーブルにユーザーが登録されています。

Supabaseに登録したユーザーを見る方法

Table Editorから schema authを選択
usersテーブルを選択

SQL Editorから
SQL文を入力

ダッシュボードから Authentication
から見ることが出来ます。

Supabaseから認証済みユーザーデータの削除

これはシステムに登録されているので、削除手段が少ないです。

ダッシュボードから Authentication から削除できます。
AuthenticationでUsersテーブルの情報が見れます。
削除したいユーザーを選択すると、詳細な情報が見れます。
その下に削除ボタンがあるので押します。

その他

GitHub認証を応用して Google認証 等も追加できます。
ログインボタンだけは作ってあります。

GoogleからソーシャルログインのIDとSECRETを取得しておきます。

config.tomlに追記します。

config.toml
...
[auth.external.google]
enabled = true
client_id = "env(GOOGLE_CLIENT_ID)"
secret = "env(GOOGLE_SECRET)"
# Overrides the default auth redirectUrl.
redirect_uri = ""

後はGitHubと似たような感じでコードを組み立てます。

最後に

Blot.newを使うと1行のプロンプトで Next.jsとSupabaseのGitHub認証コードが出ます。
Blot.newでの出力時にエラーが出るのは .envファイルを自分で書く必要があるからです。

自分が昔GitHub認証のコードを調べたときは1週間ぐらいやった気がしましたが、今では1行で終わりです。

中身を知らないままコードを書いていっても危険だと思い、ちょっと調べてみました。
認証は Supabaseの SSRではなく @supabase/auth-helpers-nextjs を使っていました。

この記事を利用してDrizzleを使う記事を書く予定です。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?