はじめに
こんにちは。elephantnodeと申します。
普段は都内で社内情シス+Web系エンジニアとして業務しています。
新たにGoogleアカウント認証機能付きのNext.jsのアプリ開発を始めようと思い、準備していたところ、Supabase UI LibraryにSocial Authが追加されていたので、試してみました。
Supabase UI Libraryはshadcn/uiをベースとしたReactのコンポーネントライブラリです。
単純なTailwindのテンプレートではなく、様々な機能を持ち合わせたライブラリのため、追加されるファイル数も多く、既存のプロジェクトに組み込むにはかなりの慎重さが要求されます。
そのため、まずはシンプルに検証環境を、なるべく早く作成できるようになっていると良いと思いましたので、今後の開発のために記事へまとめてみました。
この記事はNext.jsのセットアップとSupabase、Vercelの連携を前提にしています
さっそく進めて行きたいと思いますが、この記事は前回のNext.js+Supabase+Vercelのセットアップについてを前提にしています。
Next.jsをセットアップしてSupabaseの環境変数を作成する方法や、SupabaseとVercelを連携する方法は前回の記事をご参照ください。
SupabaseでGoogleをAuthプロバイダーに設定する
まずはGoogle Cloudに新しいプロジェクトを作成します。
プロジェクトに移動して、APIとサービス>OAuth同意画面に進みます。
OAuth同意画面は、Google Auth Platform
という名称のようです。開始ボタンで設定を進めます。
アプリの名称を入力。サポート用のメールアドレスを入力。
次に認証するユーザーの対象を選択します。内部だと、Google Workspaceのメンバーのみが利用できるようになりますが、今回は外部で設定していきます。
連絡先情報に、Googleからのお知らせを受信するためのメールアドレスを入力します。
規約への同意にチェックして作成をクリックします。
OAuthクライアントIDの作成
最初のみOAuthの概要ページに移動します。(もしくはAPIとサービス>OAuth同意画面からも入れますし、API>サービスの認証情報からも作成画面に入れます。)
アプリケーションの種類にウェブアプリケーション
をプルダウンで選択します。
画面が変わっていろいろと出てきますが、後ほど設定するので、クライアントIDの名前だけ入力して、作成します。
クライアントIDとシークレットの情報が表示されます。コピーしておくか、JSONをダウンロードしておきましょう。
SupabaseでAuthenticationを設定
SupabaseのAuthentication
>Sign In / Providers
を開き、Auth Providers
からGoogle
をクリックします。
設定画面を開き、Enable Sign in wite Google
のトグルをオンに設定し、GCPのOAuthクライアントIDで取得したクライアントIDとシークレットを入力してSave。
再度、Auth Providers
からGoogle
を開き、Callback URL(for OAuth)
のボタンでクリップボードへCopyして、Callback URLを取得します。
GCPのAPIとサービス
>認証情報
で、先程作成したOAuth2.0クライアントIDの設定を開く。
承認済みのリダイレクトURIのフォームに、先程取得したSupbaseのCallback URL(for OAuth)
を入力して保存します。
データアクセスを設定
OAuth経由でGoogleのアカウントから取得できる情報の範囲を設定しておきます。
データアクセスで必要なスコープは下記の3つです。
.../auth/userinfo.email
...auth/userinfo.profile
openid
Google Auth Platformの設定画面で、データアクセスを開きます。
スコープを追加または削除をクリックすると、設定が開きます。
メールアドレスの参照、ユーザーの個人情報の表示、openidのチェックボックスを選択します。下側に更新ボタンがありますのでクリック。
最後、忘れずにSaveしましょう。
Next.jsでSupabase UI Libraryを使ってログイン画面を作成
前回作成したSupbase+Vercel+Next.jsの連携済みアプリにライブラリを追加します。
念の為にですが、下記の内容がローカルに設定済みです。
- Next.jsのローカルセットアップ
- SupabaseとVercelの連携が設定済み
-
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 LibraryのSocial Authentication
はデフォルトでGithub
が認証プロバイダーに設定されています。このProviderをgoogle
に変更します。
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をクリック。
http://localhost:3000/**
を入力し、Save URLs。他にもIPベースで操作するなら、同様に追加してください。
注意点として、SupabaseのRdirect URLsにローカルのURLを追加しておかないと、ログイン時に突然Vercel側のサイトに飛ぶので、びっくりします。
設定は以上です。では、テストで実行してみます。
npm run dev
サイトにアクセスすると、さっそくこの画面が出てきます。
Continue with Googleを押すと、Googleアカウントの選択が表示されます。
サービスへのポリシー同意画面です。
ログインが成功すると、Googleアカウントのメールアドレスが画面に表示されました
ログアウトボタンも右側にあります。
SupabaseのUsersにもログインしたユーザーが増えています。
Vercelでも動作を確認
SupabaseとVercelのプロジェクト連携ができていると、先程のSupabase側のURL Configrationに、Vercelの設定が反映されています。
先ほどのNext.jsをGithubにpushして、Vercelへ反映させます。
無事、Vercelでもログイン画面が表示され、ログインが機能しました
ドメインを変更している場合は、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ドライブのファイルを取得するなどスコープの内容によって、Googleに事前審査が必要になるそうです。
最後に
Supabase UI LibraryがSocial Authentication
に対応したことで、以前はマニュアルで組み込んでいたコンポーネントが標準機能のような感覚でNext.jsにインストールできて、ますますサービス側の機能開発にリソースを当てることができるようになったと思います。
ただ、ルーティングや内部の仕組みなどは、一度マニュアルで構築してみると、構造の理解が深まる上に、この先のSupabaseのRow Level Security(RLS)も絡んでくるところなので、一度はSupabase UI Libraryなしで構築してみると良いと思いました。
ここまでお読みいただき、ありがとうございました。
知見のある方から、お気づきの点などご指摘いただけると幸いです。
参考サイト
参考にさせていただきました。ありがとうございます。