2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.jsとSupabase Ui Libraryで作るGoogleアカウント認証サイト

Posted at

はじめに

こんにちは。elephantnodeと申します。

普段は都内で社内情シス+Web系エンジニアとして業務しています。

新たにGoogleアカウント認証機能付きNext.jsのアプリ開発を始めようと思い、準備していたところ、Supabase UI LibrarySocial Authが追加されていたので、試してみました。

Supabase UI Libraryshadcn/uiをベースとしたReactのコンポーネントライブラリです。

単純なTailwindのテンプレートではなく、様々な機能を持ち合わせたライブラリのため、追加されるファイル数も多く、既存のプロジェクトに組み込むにはかなりの慎重さが要求されます。

そのため、まずはシンプルに検証環境を、なるべく早く作成できるようになっていると良いと思いましたので、今後の開発のために記事へまとめてみました。

この記事はNext.jsのセットアップとSupabase、Vercelの連携を前提にしています

さっそく進めて行きたいと思いますが、この記事は前回のNext.js+Supabase+Vercelのセットアップについてを前提にしています。

Next.jsをセットアップしてSupabaseの環境変数を作成する方法や、SupabaseとVercelを連携する方法は前回の記事をご参照ください。

SupabaseでGoogleをAuthプロバイダーに設定する

まずはGoogle Cloudに新しいプロジェクトを作成します。

新しいプロジェクト_–ダッシュボード–elephantnode_com–_Google_Cloud_コンソール.png

プロジェクトに移動して、APIとサービス>OAuth同意画面に進みます。

Cursor_と_ダッシュボード_–nextjs-myapp–_Google_Cloud_コンソール.png

OAuth_の概要_–Google_Auth_Platform–nextjs-myapp–_Google_Cloud_コンソール.png

OAuth同意画面は、Google Auth Platformという名称のようです。開始ボタンで設定を進めます。

プロジェクト構成_–Google_Auth_Platform–nextjs-myapp–_Google_Cloud_コンソール.png

アプリの名称を入力。サポート用のメールアドレスを入力。

次に認証するユーザーの対象を選択します。内部だと、Google Workspaceのメンバーのみが利用できるようになりますが、今回は外部で設定していきます。

プロジェクト構成_–Google_Auth_Platform–nextjs-myapp–Google_Cloud_コンソール_と_Google_Chat-_Chat.png

プロジェクト構成_–Google_Auth_Platform–nextjs-myapp–_Google_Cloud_コンソール_と_Next_js___supabase___vercelでGoogle認証付きサイトを作ってみる.png

連絡先情報に、Googleからのお知らせを受信するためのメールアドレスを入力します。

プロジェクト構成_–Google_Auth_Platform–nextjs-myapp–_Google_Cloud_コンソール_と_Next_js___supabase___vercelでGoogle認証付きサイトを作ってみる.png

規約への同意にチェックして作成をクリックします。

OAuthクライアントIDの作成

OAuth_の概要_–Google_Auth_Platform–nextjs-myapp–_Google_Cloud_コンソール.png

最初のみOAuthの概要ページに移動します。(もしくはAPIとサービス>OAuth同意画面からも入れますし、API>サービスの認証情報からも作成画面に入れます。)

OAuth_クライアント_ID_の作成_–Google_Auth_Platform–nextjs-myapp–_Google_Cloud_コンソール.png

アプリケーションの種類にウェブアプリケーションをプルダウンで選択します。

OAuth_クライアント_ID_の作成_–Google_Auth_Platform–nextjs-myapp–_Google_Cloud_コンソール.png

画面が変わっていろいろと出てきますが、後ほど設定するので、クライアントIDの名前だけ入力して、作成します。

OAuth_クライアント_ID_の作成_–Google_Auth_Platform–nextjs-myapp–_Google_Cloud_コンソール.png

クライアントIDとシークレットの情報が表示されます。コピーしておくか、JSONをダウンロードしておきましょう。

SupabaseでAuthenticationを設定

SupabaseのAuthentication>Sign In / Providersを開き、Auth ProvidersからGoogleをクリックします。

Cursor_と_Authentication___Supabase.png

Authentication___Supabase.png

設定画面を開き、Enable Sign in wite Googleのトグルをオンに設定し、GCPのOAuthクライアントIDで取得したクライアントIDシークレットを入力してSave。

Authentication___Supabase_と_Next_js___supabase___vercelでGoogle認証付きサイトを作ってみる.png

再度、Auth ProvidersからGoogleを開き、Callback URL(for OAuth)のボタンでクリップボードへCopyして、Callback URLを取得します。

Cursor_と_認証情報_–API_とサービス–nextjs-myapp–_Google_Cloud_コンソール.png

GCPのAPIとサービス認証情報で、先程作成したOAuth2.0クライアントIDの設定を開く。

Cursor_と_ウェブ_アプリケーション_のクライアント_ID_–Google_Auth_Platform–nextjs-myapp–Google_Cloud_コンソール_と_Vue3とSupabaseで作るGoogleアカウント認証サイト__Vue_js-_Qiita_🔊_と_Next_js___supabase___vercelでGoogle認証付きサイトを作ってみる.png

承認済みのリダイレクトURIのフォームに、先程取得したSupbaseCallback URL(for OAuth)を入力して保存します。

データアクセスを設定

OAuth経由でGoogleのアカウントから取得できる情報の範囲を設定しておきます。

データアクセスで必要なスコープは下記の3つです。

.../auth/userinfo.email
...auth/userinfo.profile
openid

Google Auth Platformの設定画面で、データアクセスを開きます。

データアクセス_–Google_Auth_Platform–nextjs-myapp–_Google_Cloud_コンソール.png

スコープを追加または削除をクリックすると、設定が開きます。

Cursor_と_データアクセス_–Google_Auth_Platform–nextjs-myapp–_Google_Cloud_コンソール.png

メールアドレスの参照、ユーザーの個人情報の表示、openidのチェックボックスを選択します。下側に更新ボタンがありますのでクリック。

Cursor_と_データアクセス_–Google_Auth_Platform–nextjs-myapp–_Google_Cloud_コンソール.png

最後、忘れずにSaveしましょう。

Next.jsでSupabase UI Libraryを使ってログイン画面を作成

前回作成したSupbase+Vercel+Next.jsの連携済みアプリにライブラリを追加します。

念の為にですが、下記の内容がローカルに設定済みです。

  • Next.jsのローカルセットアップ
  • SupabaseVercelの連携が設定済み
  • Supabaseの環境変数をNext.js.env.localに取得済み

まずはSupabaseのパッケージをインストールします。

npm install @supabase/supabase-js @supabase/ssr

次に、Supabase UI LibraryからSocial Authenticationをインストールします。

❯ npx shadcn@latest add https://supabase.com/ui/r/social-auth-nextjs.json

? You need to create a components.json file to add components. Proceed? › (Y/n)
? Which color would you like to use as the base color? › - Use arrow-keys. Return to submit.
❯   Neutral
    Gray
    Zinc
    Stone
    Slate
✔ Writing components.json.
✔ Checking registry.
  Installing dependencies.

It looks like you are using React 19. 
Some packages may fail to install due to peer dependency issues in npm (see https://ui.shadcn.com/react-19).

? How would you like to proceed? › - Use arrow-keys. Return to submit.
❯   Use --force
    Use --legacy-peer-deps

Use --force
✔ Installing dependencies.
✔ Created 12 files:
  - src/app/auth/login/page.tsx
  - src/app/auth/error/page.tsx
  - src/app/protected/page.tsx
  - src/app/auth/oauth/route.ts
  - src/components/login-form.tsx
  - src/middleware.ts
  - src/components/logout-button.tsx
  - src/lib/supabase/client.ts
  - src/lib/supabase/middleware.ts
  - src/lib/supabase/server.ts
  - src/components/ui/button.tsx
  - src/components/ui/card.tsx

インストール中に設定が必要な項目は3つです。

1つ目はインストールの確認、2つ目はベースカラーの選択です。

最後はNext.jsのlatestが現時点ではNext.js15+React 19環境なので、Supabase UI Libraryで採用しているコンポーネントライブラリのshadcn/uiがそのままインストールしようとするとパッケージの依存関係でエラーが発生するため、強制的にインストールするためのコマンドを選ぶ必要があるとのことです。

すべてに答えるとインストールは完了しました。

Next.jsのアプリを確認すると、すっからかんだったsrcフォルダに、様々なファイルが増えていることを確認できます。

以下srcの構成内容です。

❯ tree -a     
.
├── app
│   ├── auth
│   │   ├── error
│   │   │   └── page.tsx
│   │   ├── login
│   │   │   └── page.tsx
│   │   └── oauth
│   │       └── route.ts
│   ├── favicon.ico
│   ├── globals.css
│   ├── layout.tsx
│   ├── page.tsx
│   └── protected
│       └── page.tsx
├── components
│   ├── login-form.tsx
│   ├── logout-button.tsx
│   └── ui
│       ├── button.tsx
│       └── card.tsx
├── lib
│   ├── supabase
│   │   ├── client.ts
│   │   ├── middleware.ts
│   │   └── server.ts
│   └── utils.ts
└── middleware.ts

10 directories, 17 files

OAuthログインプロバイダーを変更する

さきほどログインに必要なコンポーネントが一式インストールされましたが、Supabase Ui LibrarySocial AuthenticationはデフォルトでGithubが認証プロバイダーに設定されています。このProviderをgoogle に変更します。

src/components/login-form.tsxを編集します。

src/components/login-form.tsx
'use client'

import { cn } from '@/lib/utils'
import { createClient } from '@/lib/supabase/client'
import { Button } from '@/components/ui/button'
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from '@/components/ui/card'
import { useState } from 'react'

export function LoginForm({ className, ...props }: React.ComponentPropsWithoutRef<'div'>) {
  const [error, setError] = useState<string | null>(null)
  const [isLoading, setIsLoading] = useState(false)

  const handleSocialLogin = async (e: React.FormEvent) => {
    e.preventDefault()
    const supabase = createClient()
    setIsLoading(true)
    setError(null)

    try {
      const { error } = await supabase.auth.signInWithOAuth({
        provider: 'github',
        options: {
          redirectTo: `${window.location.origin}/auth/oauth?next=/protected`,
        },
      })

      if (error) throw error
    } catch (error: unknown) {
      setError(error instanceof Error ? error.message : 'An error occurred')
      setIsLoading(false)
    }
  }

  return (
    <div className={cn('flex flex-col gap-6', className)} {...props}>
      <Card>
        <CardHeader>
          <CardTitle className="text-2xl">Welcome!</CardTitle>
          <CardDescription>Sign in to your account to continue</CardDescription>
        </CardHeader>
        <CardContent>
          <form onSubmit={handleSocialLogin}>
            <div className="flex flex-col gap-6">
              {error && <p className="text-sm text-destructive-500">{error}</p>}
              <Button type="submit" className="w-full" disabled={isLoading}>
                {isLoading ? 'Logging in...' : 'Continue with Github'}
              </Button>
            </div>
          </form>
        </CardContent>
      </Card>
    </div>
  )
}

Supabaseのクライアントでsupabase.auth.signInWithOAuthに設定されているproviderをGooogleに変更します。

      const { error } = await supabase.auth.signInWithOAuth({
-       provider: 'github',
+       provider: 'google',
        options: {
          redirectTo: `${window.location.origin}/auth/oauth?next=/protected`,
        },
      })

せっかくなので、ボタンの名称部分も変更しておきます。

              <Button type="submit" className="w-full" disabled={isLoading}>
-                {isLoading ? 'Logging in...' : 'Continue with Github'}
+                {isLoading ? 'Logging in...' : 'Continue with Google'}
              </Button>

ローカルでテスト

ここまで来たら、いよいよローカルでテストしてみましょう!!

Next.jsはローカルテストで動かすと、http://localhost:3000/のURLで検証されると思います。Supabaseは認証時のリダイレクトで利用可能なURLをセキュリティ上でチェックしている箇所があるので、Supabase
の管理画面でローカル環境のリダイレクト先URLhttp://localhost:3000/**を追加します。

Authentication > URL Configurationへ進み、Redirect URLsのAdd URLをクリック。

Cursor_と_Authentication___Supabase.png

Cursor_と_Authentication___Supabase.png

http://localhost:3000/**を入力し、Save URLs。他にもIPベースで操作するなら、同様に追加してください。

注意点として、SupabaseのRdirect URLsにローカルのURLを追加しておかないと、ログイン時に突然Vercel側のサイトに飛ぶので、びっくりします。

設定は以上です。では、テストで実行してみます。

npm run dev

Cursor_と_Create_Next_App.png

サイトにアクセスすると、さっそくこの画面が出てきます。

https___qiita-image-store_s3_ap-northeast-1_amazonaws_com_0_38388_63716833-83c3-4458-a319-d8b2562a722e.png

Continue with Googleを押すと、Googleアカウントの選択が表示されます。

https___qiita-image-store_s3_ap-northeast-1_amazonaws_com_0_38388_0c1571b8-6b6d-460e-a9db-e1e07ae35242.png

サービスへのポリシー同意画面です。

Cursor_と_Create_Next_App.png

ログインが成功すると、Googleアカウントのメールアドレスが画面に表示されました:tada:
ログアウトボタンも右側にあります。

Cursor_と_Authentication___Supabase_と_login-form_tsx_—_nextjs-myapp.png

SupabaseのUsersにもログインしたユーザーが増えています。

Vercelでも動作を確認

SupabaseVercelのプロジェクト連携ができていると、先程のSupabase側のURL Configrationに、Vercelの設定が反映されています。

Cursor_と_Authentication___Supabase.png

先ほどのNext.jsをGithubにpushして、Vercelへ反映させます。

Create_Next_App.png

Create_Next_App.png

無事、Vercelでもログイン画面が表示され、ログインが機能しました:tada:

ドメインを変更している場合は、URL Configrationのドメインも変更が必要になります。

もう少しログインを修正

Supabaseクライアントsupabase.auth.signInWithOAuthは、Googleでログインすると、Cookieに保存されて、次回も同じアカウントでログインするようになっており、アカウントの変更がデフォルトではできません。(Cookieを削除すれば切り替えは可能)

複数アカウントを切り替えてテストしたい場合などに不便なので、毎回ログインアカウントを選択できるように変更します。

      const { error } = await supabase.auth.signInWithOAuth({
        provider: 'google',
        options: {
          redirectTo: `${window.location.origin}/auth/oauth?next=/protected`,
        },
+       queryParams: {
+           access_type: 'offline',
+           prompt: 'consent',
+       },
      })

Google Auth Platformのアプリ公開について

アプリはテストモードとなっていますので、実際のサービス公開の際にはGoogle Auth Platformの対象のメニューからアプリを公開する必要があります。

対象_–Google_Auth_Platform–nextjs-myapp–_Google_Cloud_コンソール.png

アプリの設計にもよりますが、Googleドライブのファイルを取得するなどスコープの内容によって、Googleに事前審査が必要になるそうです。

最後に

Supabase UI LibrarySocial Authenticationに対応したことで、以前はマニュアルで組み込んでいたコンポーネントが標準機能のような感覚でNext.jsにインストールできて、ますますサービス側の機能開発にリソースを当てることができるようになったと思います。

ただ、ルーティングや内部の仕組みなどは、一度マニュアルで構築してみると、構造の理解が深まる上に、この先のSupabaseRow Level Security(RLS)も絡んでくるところなので、一度はSupabase UI Libraryなしで構築してみると良いと思いました。

ここまでお読みいただき、ありがとうございました。

知見のある方から、お気づきの点などご指摘いただけると幸いです。

参考サイト

参考にさせていただきました。ありがとうございます。

2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?