SIMPLE

【Supabase】Next.jsでGoogleソーシャルログインを実装する方法(後編)

前編と後編に分けて、SupabseでGoogle ソーシャルログインを実装する方法をまとめます。後編ではSupabaseによるGoogle ソーシャルログインの実装を行います。

通りすがりのラマ🦙
22 February, 2025

サムネイルはUnsplashSilas Köhlerが撮影した写真

はじめに

前編では、「Googleログイン」ボタンについて解説しました。後編では、「Googleログイン」ボタンとSupabaseを組み合わせて、ソーシャルログイン(Social Login)を実装する手順を解説します。

本記事で解説する内容

  • Googleが提供している「Googleでログイン」ボタンの種類や実装方法(前編)
  • Supabaseを使ったGoogleでのSocial Loginの実装方法(後編)←本記事

前編はこちらです。

結論


前提

  1. Next.js用の認証チュートリアルの「3Write utility functions to create Supabase clients」まで完了していること
    • @supabase/supabase-js @supabase/ssrがインストール済み
    • 環境変数を設定済み(NEXT_PUBLIC_SUPABASE_URL、NEXT_PUBLIC_SUPABASE_ANON_KEY)
    • supabaes clientを実装済み(client/serverともに)

  2. Supabaseの「User Management Starter」を実行済み
    • 「SQL Editor」>「Quickstarts」>「User Management Starter」
User Management Starter
User Management Starter
User Management Starter SQL実行画面
User Management Starter SQL実行画面

補足:

  • 本記事ではサーバサイドでの認証処理を行っていないので、ミドルウェアは実装しなくても動きます。サーバサイドで認証処理をする際は、ミドルウェアも導入してください。
  • 認証情報を保存するデータベースのセットアップは「User Management Starter」テンプレートを使用して行います。セットアップ後、必要に応じてテーブルスキーマは変更できます。

環境準備

Google Cloud側の設定

今回のSocial Loginでは、GoogleをIdpとして利用します。まずはGoogle Cloudでの設定を行っていきます。公式ドキュメントはこちらです。

1. プロジェクトを構成する(初回利用時のみ)

Google CloudのAuth Platformでプロジェクトの構成を行います。

開始をクリックします。

Google Auth Platform概要画面
Google Auth Platform概要画面

アプリ名とユーザサポートメールを入力します。

プロジェクト構成画面(アプリ情報)
プロジェクト構成画面(アプリ情報)

対象に「外部」を選択します。

プロジェクト構成画面(対象)
プロジェクト構成画面(対象)

連絡先情報を入力します。

プロジェクト構成画面(連絡先情報)
プロジェクト構成画面(連絡先情報)

ポリシーに同意します。

プロジェクト構成画面(終了)
プロジェクト構成画面(終了)

作成をクリックすると、プロジェクトが構成されます。

プロジェクト構成画面(作成)
プロジェクト構成画面(作成)

2. OAuth クライアントの作成

「OAuthクライアントを作成」をクリックします。

OAuthの概要画面
OAuthの概要画面

以下のデータを入力して、作成をクリックします。今回はローカル環境でテストをします。本番環境にデプロイする際は、本番環境のドメインも追加してください。

  • アプリケーションの種類:ウェブアプリケーション
  • 名前:任意
  • 承認済みのJavaScript生成元
    • http://localhost
    • http://localhost:3000
  • 承認済みのリダイレクトURI
    • http://localhost
    • http://localhost:3000

補足:localhostとlocalhost:3000を両方追加する理由

https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid?hl=ja

キーポイント: ローカルテストまたは開発の場合は、http://localhosthttp://localhost:<port_number> の両方を追加します。

クライアントIDをコピーします。

OAuth クライアント画面
OAuth クライアント画面

Supabase側の設定

Supabaseのダッシュボードから、先ほどコピーしたクライアントIDを設定します。「Authentication」>「Sign In/Up」>「Google」で遷移します。

Client IDsに先ほどコピーしたクライアントIDをペーストして、保存します。

Googleログインボタンの実装

HTMLでのGoogleログインボタンの実装

コード

https://github.com/g-ishi/supabase-google-social-login/blob/main/src/app/login/HtmlBaseLoginButton.tsx

'use client';
import { createClient } from '@/utils/supabase/client';
import { useRouter } from 'next/navigation';
import Script from 'next/script';
import { useEffect } from 'react';

// グローバルな型定義を追加
declare global {
  interface Window {
    handleSignInWithGoogle: (response: GoogleResponse) => Promise<void>;
  }
}

interface GoogleResponse {
  credential: string;
}

export const HtmlBaseLoginButton = () => {
  const router = useRouter();

  // コンポーネントがマウントされる時にコールバックを設定
  useEffect(() => {
    window.handleSignInWithGoogle = async (response: GoogleResponse) => {
      const supabase = createClient();

      try {
        const { data, error } = await supabase.auth.signInWithIdToken({
          provider: 'google',
          token: response.credential,
        });

        console.log(data);
        router.refresh();
        router.push('/account'); // ログイン後のリダイレクト先
      } catch (error) {
        console.log(error);
      }
    };

    // クリーンアップ関数
    return () => {
      // delete window.handleSignInWithGoogle;
      delete (window as any).handleSignInWithGoogle;
    };
  }, []);

  return (
    <>
      <Script
        src='https://accounts.google.com/gsi/client'
        strategy='afterInteractive'
      />
      <div
        id='g_id_onload'
        data-client_id={process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID}
        data-context='signin'
        data-ux_mode='popup'
        data-callback='handleSignInWithGoogle'
        data-itp_support='true'
        data-use_fedcm_for_prompt='true'
      ></div>

      <div
        className='g_id_signin'
        data-type='standard'
        data-shape='pill'
        data-theme='outline'
        data-text='signin_with'
        data-size='large'
        data-logo_alignment='left'
      ></div>
    </>
  );
};

解説

Scriptタグで「Googleログイン」ボタンをレンダリングするためのスクリプトを読み込んでいます。このサンプルコードではコンポーネント内に定義していますが、Layout.tsxなどに移してもいいと思います。

      <Script
        src='https://accounts.google.com/gsi/client'
        strategy='afterInteractive'
      />

Googleボタンの見た目やサインイン方法などを定義しています。HTMLコードはGoogleが提供しているこちらを使用して生成しています。

      <div
        id='g_id_onload'
        data-client_id={process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID}
        data-context='signin'
        data-ux_mode='popup'
        data-callback='handleSignInWithGoogle'
        data-itp_support='true'
        data-use_fedcm_for_prompt='true'
      ></div>

      <div
        className='g_id_signin'
        data-type='standard'
        data-shape='pill'
        data-theme='outline'
        data-text='signin_with'
        data-size='large'
        data-logo_alignment='left'
      ></div>

Scriptタグで読み込んだGoogleのコードが関数を呼び出せるようにするために、コールバック関数をグローバルに登録します。

window.handleSignInWithGoogle = async (response: GoogleResponse) => {

参考:https://supabase.com/docs/guides/auth/social-login/auth-google#google-pre-built

Create a handleSignInWithGoogle function that takes the CredentialResponse and passes the included token to Supabase. The function needs to be available in the global scope for Google's code to find it.

Googleから返却されたIDトークン(credential)をsupabaseに渡します。これをもとに、SupabaseがGoogleとやりとりをして、認証やセッションの払い出しを行います。

const { data, error } = await supabase.auth.signInWithIdToken({
          provider: 'google',
          token: response.credential,
        });

補足:HTMLコードを生成ページの使い方

以下のデータ入力します。

  • クライアントID:作成したOAuth ClientのクライアントID(サンプルコードでは環境変数で置き換えています。)
  • データコンテキスト:ログイン
  • コールバック関数:任意の関数名(サンプルコードではhandleSignInWithGoogle)
    • グローバル(windowオブジェクト)に定義されている必要があります。

有効にするログイン方法の選択と、見た目のカスタマイズを行います。サンプルコードでは、One Tapと「Googleでログイン」ボタンの両方を有効にしています。

生成したコードをコピーして使用します。

JavaScriptでの「Googleでログイン」ボタンの実装

コードはこちらです。解説はHTMLで実装したものとほぼ同じなので割愛します。

https://github.com/g-ishi/supabase-google-social-login/blob/main/src/app/login/JavascriptBaseLoginButton.tsx

動作確認

開発サーバを起動し、認証の動作確認をします。右上にOne Tapのポップアップ、中央に「Googleでログイン」ボタンが表示されます。どちらからでもログイン可能です。(Next.jsのエラーは本題とは関係がないので、無視します。)

http://localhost:3000/login
http://localhost:3000/login

ログインに成功すると、/account画面にリダイレクトします。ログインしたユーザのプロフィール画像とメールメールアドレスが表示されていれば成功です。

http://localhost:3000/account
http://localhost:3000/account

SupabaseのダッシュボードからもGoogleでログインしているセッションが払い出されたことが確認できます。

Supabase/Authentication画面
Supabase/Authentication画面

以上で、SupabaseでGoogle Social Loginの実装は完了です。

おわりに

本記事では、SupabaseでGoolgeを認証プロバイダーとしたSocial Loginの実装を行いました。Googleが提供するスクリプトを使うことで、UXのよいログインフローを少ないコードで実装することができます。

私は最初にSupabaseのチュートリアルをやった際に、どこまでがGoogle/Supabaseが提供しているものか、またGoogleが提供しているログイン方法を知らず、全体を理解するのに時間がかかりました。

この記事が同じような方の理解の助けになれば幸いです。フィードバックやコメントも大歓迎です。🦙

最後までご覧いただきありがとうございました。

通りすがりのラマ🦙

このブログでは、個人開発で得た知見や、興味のあるテクノロジー、時々デザインに関する記事を執筆します。 日々公開されている情報に助けられているので、自分が得た知見も世の中に還元していければと思います。 解決できないバグに出会うと、つばを飛ばします。🦙 経歴:情報工学部→日系SIer→外資系IT企業 興味:Webアプリケーション開発、Webデザイン 趣味:個人開発、テニス