メインコンテンツへスキップ
チュートリアル

React で Capacitor、Supabase、Social Auth を使う方法

ReactとCapacitorでSupabase認証を実装するステップバイステップのチュートリアル。@capgo/capacitor-social-login.のGoogle/Appleネイティブサインイン、nonce対応のsignInWithIdToken、モバイルにリリースできるViteアプリを解説します。

React で Capacitor、Supabase、Social Auth を使う方法

GoogleとAppleのネイティブサインインを React アプリに実装し、 Supabase Authでバックエンドを構築しましょう, そして同じUIをラップします。 Capacitor モバイルブラウザのリダイレクトに悩まされることもありません。 Capgo ソーシャルログイン (@capgo/capacitor-social-login) handles the native provider sheets; you exchange the provider ID token for a Supabase session with signInWithIdToken.

この記事では、既存の Supabase + Social Login ガイドを拡張し、 React + Vite の完全な walkthrough(プロジェクト構成、プロバイダー、ルート、Capacitor の連携)を提供します。プロバイダーのダッシュボードやプラットフォームキーについては、引き続き Supabase連携ドキュメント および Google + Supabase の一般的なセットアップ を参照してください。関連記事: Capacitor を使った Google サインイン, Capacitor を使った Apple サインインや Capacitor での認証オプション.

目次

構築する内容

  • ある Vite + React + TypeScript サインインボタンとログイン後のデバッグビューを備えたWebアプリ
  • Supabase Auth ネイティブで作成されたセッション Google (およびオプションの Apple) IDトークン)
  • 同じbundleが以下で動作します Capacitor iOSおよびAndroid上で
  • nonce安全なGoogleフロー(以下に準拠) pluginのサンプルアプリ

認証フローの全体像

を使用すると、 @capgo/capacitor-social-login、モバイルアプリは 決して 依存する signInWithOAuth WebView内でのリダイレクトに依存します。ネイティブの SDK は IDトークンを返します。Supabaseがこれを検証し、独自のJWTを発行します。

React UIから Capgo Social LoginとGoogleを経由してSupabase Authへ至るフロー

オンラインに ウェブの場合でも、同じプラグインを使用できます(詳細は Googleウェブ設定を参照)。後でブラウザへのフォールバックを追加する場合は、ルーターでOAuthのリターンURLを処理してください。

ベースとなるReact (Vite) アプリケーション

新規アプリの作成(または既存のReactコードベースの再利用):

bun create vite capgo-supabase-auth --template react-ts
cd capgo-supabase-auth
bun install
bun add @supabase/supabase-js @capgo/capacitor-social-login react-router-dom @capacitor/core

開発サーバーの起動:

bun run dev

SupabaseとSocial Loginインストール後のローカルVite開発サーバー

ターゲットフォルダの構成:

Supabase auth helpersとReactページ推奨のsrc構成

環境変数の追加先: .env.local (機密情報は絶対にコミットしないでください):

VITE_SUPABASE_URL=https://your-project-ref.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-public-key
VITE_GOOGLE_WEB_CLIENT_ID=your-web-client-id.apps.googleusercontent.com
VITE_GOOGLE_IOS_CLIENT_ID=your-ios-client-id.apps.googleusercontent.com
VITE_APPLE_SERVICE_ID=com.yourapp.signin
VITE_SUPABASE_APPLE_CALLBACK_URL=https://your-project-ref.supabase.co/functions/v1/apple-signin-callback

Social LoginでSupabaseを使う理由

Supabaseは 認証機能内蔵の強力なBaaSを提供し、 @capgo/capacitor-social-login pluginはiOS、Android、Webプラットフォームでネイティブなソーシャル認証を実現します。Supabaseとの連携を強化するには、 @capgo/capacitor-supabase ネイティブの認証ヘルパーとJWTアクセスを追加します。これらを組み合わせることで、以下が可能になります:

  • シームレスなソーシャル認証
  • セキュアなトークン管理
  • クロスプラットフォーム対応
  • リアルタイムなデータベース連携
  • 組み込みのユーザー管理

前提条件

開始する前に、以下を確認してください:

  • Capacitor プロジェクトのセットアップ
  • Supabaseのアカウントとプロジェクト
  • 選択したソーシャルプロバイダー(Google、Apple、Facebook)のデベロッパーアカウント

ステップ 1: Social Login プラグインのインストールと設定

まず、Capgo Social Login プラグインをインストールします:

bun add @capgo/capacitor-social-login

実行 bunx cap sync その後 Capacitor とネイティブプラットフォームを次に追加します: ReactアプリにCapacitorを追加する。以下の Vite 専用のチュートリアルは、そのステップの前のブラウザ環境でも動作します。

詳細については、 ソーシャルログイン と Supabase プラグインの各ページで、プラットフォームごとの設定を確認してください。

ステップ 2: Supabase プロジェクトのセットアップ

ID トークンによる Google サインインを有効にするための Supabase ダッシュボードチェックリスト

Supabase プロジェクトの作成と設定

  1. Supabase プロジェクトを作成する:

    • 以下に移動します: supabase.com およびサインアップ/サインイン
    • クリック 「新規プロジェクト」
    • 組織を選択
    • 以下を入力 プロジェクト名 (例: “MyApp Auth”)
    • 以下を設定します: データベースのパスワード (安全に保管してください)
    • 次を選択: リージョン (ユーザーに最も近い場所を選択)
    • クリック 「新規プロジェクトを作成」
  2. プロジェクトの認証情報を取得:

    • 作成後、以下へ移動します: 設定 > API
    • 以下の情報をコピーしてください: プロジェクトURL (例: https://your-project-ref.supabase.co)
    • 以下の情報をコピーしてください: anon public API キー
    • アプリで使用するため、これらを保存しておいてください

認証設定の構成

  1. 一般的な認証設定を行います:

    • 以下に移動します: 認証 > 設定
    • 未満 全般設定:
      • 設定 サイトURL アプリのURLを入力(例: https://yourdomain.com または http://localhost:3000 開発用)
      • 追加の リダイレクトURL が必要な場合:
        http://localhost:3000
        https://yourdomain.com
        capacitor://localhost (for mobile apps)
  2. メール設定を構成 (任意ですが推奨):

    • 未満 SMTP設定メールプロバイダーを設定してください
    • これにより、メール確認やパスワードリセットが可能になります
    • 開発時は、組み込みのメールサービスを利用できます

ソーシャル認証プロバイダーを有効にする

  1. プロバイダーセクションにアクセスし、:
    • 以下に移動します: Authentication > Providers に移動します。 Supabase dashboardを開きます
    • 利用可能なソーシャルプロバイダーの一覧が表示されます
    • 各プロバイダーには 有効にする トグルと設定オプション

それでは、各ソーシャルプロバイダーの詳細設定を行っていきましょう。

ステップ 3: Supabase でソーシャルプロバイダーを設定する

Supabase で Google 認証を設定する

まず、Google OAuth の認証情報を取得します。

こちらの Google 設定ガイドに従ってください: Google 認証の設定

このガイドの内容:

  • Google Cloud プロジェクトの作成
  • Web、iOS、Android 用の OAuth 2.0 認証情報の作成
  • 同意画面の設定
  • 必要な Client ID とシークレットの取得

Googleの設定完了後、Supabaseで設定してください:

最初のアップデートを送信するには、 Supabase + Google の総合ガイド 各ダッシュボードのクリック箇所のスクリーンショットは

  1. SupabaseでGoogleプロバイダーを有効にする:
    • Supabaseダッシュボードで、 Authentication > Providers に移動します。
    • 次を探して、 Google のスイッチを ON
    • 次を追加します: Web, iOSとや Android Google Cloudで作成したクライアントID(提供していないプラットフォームはスキップ)
    • クリック 保存

このReactチュートリアルで重要なポイント: を使用する場合 signInWithIdToken を使用して @capgo/capacitor-social-login、次のようにします 決して OAuthが必要です クライアントシークレット またはGoogleのコールバックURLフィールドが必要です。各プラットフォームからのトークン検証時にSupabaseが受け入れられるすべてのクライアントIDを登録してください。

SupabaseでのApple Authenticationの設定

Appleの認証情報を取得します:

詳細なApple設定ガイドに従ってください: Apple Authenticationの設定

このガイドの内容:

  • Apple Developerアカウントの設定
  • App IDとService IDの作成
  • Sign in with Apple機能の設定
  • 必要なプライベートキーの生成
  • iOS、Android、Web向けのプラットフォーム別設定

Appleの設定完了後、Supabaseで以下の設定を行ってください:

  1. SupabaseでAppleプロバイダーを有効にする:
    • 以下に移動します: Authentication > Providers に移動します。 を切り替えて Apple ON
    • 設定を入力してください:
      • クライアントID:両方のプラットフォームをリリースする場合は、iOS App IDとApple Service IDをカンマ区切りで入力してください(例: com.yourapp,com.yourapp.signin)。iOSトークンはApp IDのaudienceを使用し、AndroidとWebはService IDを使用します。詳細は SupabaseでのApple認証全般.
      • 本チュートリアルの signInWithIdToken フローでは、 @capgo/capacitor-social-login、次のようにします 決して Appleプロバイダー設定に、OAuthクライアントシークレットまたはSupabaseのOAuthコールバックURLが必要です。
    • クリック 保存

注意: Apple認証の設定は、Service ID、秘密鍵、プラットフォーム固有のリダイレクトURLなど、Apple独自の要件があるため最も複雑です。各プラットフォームのドキュメントを注意深く確認してください。

SupabaseでのFacebook認証の設定

Facebookの認証情報を取得:

Facebookの設定に関する完全ガイドはこちら: Facebook認証の設定方法

このガイドの内容:

  • Facebook Developerアカウントとアプリの作成
  • Facebook Login製品の追加
  • OAuthリダイレクトURIの設定
  • App ID、App Secret、Client Tokenの取得
  • iOSおよびAndroid向けのプラットフォーム別設定

Facebookの設定完了後、Supabaseで以下の設定を行ってください:

  1. SupabaseでFacebookプロバイダーを有効にする:
    • 以下に移動します: Authentication > Providers に移動します。 を切り替えて Facebook ON
    • 設定を入力してください:
      • クライアントID:Facebook App ID
      • クライアントシークレット:Facebook App Secret
      • リダイレクトURL: https://your-project-ref.supabase.co/auth/v1/callback (自動入力)
    • クリック 「保存」

重要: SupabaseのコールバックURL ("https://your-project-ref.supabase.co/auth/v1/callback") をFacebookアプリの 有効なOAuthリダイレクトURI に必ず追加してください(Facebook Login設定内)。

Supabase設定に関する重要な注意点

行レベルセキュリティ (RLS):

  • 認証の設定後、テーブルのRLSを有効にしてください
  • 以下に移動します: Database > Tables を切り替えて RLSを有効にする 各テーブルに対して
  • 認証済みユーザーに基づいたデータアクセス制御用のポリシーを作成します

ユーザー管理:

  • 認証済みユーザーの確認: Authentication > Users
  • 認証イベントの監視: Authentication > Logs
  • メールテンプレートの設定: Authentication > Email Templates

設定のテスト:

  • Supabase内蔵の認証テストツールを使用します
  • 以下に移動します: Authentication > Users をクリックし、 「ユーザーを招待」 でメールフローをテストします
  • チェック: ログ 認証エラーを確認するセクション

ステップ 4: Social Login プラグインの設定

Supabase の設定が完了したので、対応する認証情報で Social Login プラグインをセットアップする必要があります。 重要: プラグインには、OAuth 認証情報が必要です。 元のプロバイダー (Supabase経由ではなく)、Supabaseはサーバー側の認証を処理します。

認証フローの仕組み

設定に入る前に、フローを理解しておきましょう:

  1. プラグインが認証を実行 ソーシャルプロバイダー(Google/Apple/Facebook)とネイティブで連携
  2. プラグインがトークンを受信 プロバイダーから(アクセストークン、IDトークン)を取得
  3. アプリがこれらのトークンを送信 Supabaseへ送信 signInWithIdToken()
  4. Supabaseが検証 プロバイダーとトークンを照合し、ユーザーセッションを作成
  5. Supabaseが返却 アプリの認証リクエスト用の独自のJWTトークン

Googleプラグインの設定

プラグインには以下が必要です: WebクライアントID 全プラットフォーム用、および任意で iOS クライアント ID iOS固有の機能を使用する場合:

import { SocialLogin } from '@capgo/capacitor-social-login';

await SocialLogin.initialize({
  google: {
    // Use the same Web Client ID you configured in Supabase
    webClientId: 'YOUR_WEB_CLIENT_ID.apps.googleusercontent.com',
    
    // Optional: iOS Client ID for iOS-specific features
    iOSClientId: 'YOUR_IOS_CLIENT_ID.apps.googleusercontent.com',
    
    // Use online mode so the plugin returns an idToken for Supabase
    mode: 'online'
  }
});

Google設定の重要ポイント:

  • 以下の WebクライアントID (Android/iOSのクライアントIDではなく) 対象の webClientId フィールド用
  • Web Client ID さえあれば、全プラットフォームで動作します
  • この iOSClientId は任意で、iOS固有のGoogle機能を使用する場合のみ必要です

Apple プラグインの設定

Apple の設定は iOS と Android で異なります:

iOS向け (ネイティブの Apple Sign-In):

await SocialLogin.initialize({
  apple: {
    // No additional configuration needed for iOS
    // The plugin uses the native Apple Sign-In capability
  }
});

Android/Web の場合 (Service ID が必要)。以下のリダイレクトルールを buildApplePluginConfig() React のチュートリアルと同様に使用してください:

import { Capacitor } from '@capacitor/core';

const platform = Capacitor.getPlatform();

await SocialLogin.initialize({
  apple:
    platform === 'android'
      ? {
          clientId: 'YOUR_SERVICE_ID',
          redirectUrl:
            'https://your-project-ref.supabase.co/functions/v1/apple-signin-callback',
        }
      : {
          clientId: 'YOUR_SERVICE_ID',
          redirectUrl: window.location.href,
        },
});

Apple 設定の重要ポイント:

  • iOS はネイティブの Sign in with Apple を使用します(追加設定は不要)
  • Androidでは、Service IDとSupabaseの apple-signin-callback Edge Function URLを使用します
  • Webでは、Service IDと window.location.href、これはAppleのReturn URLと一致させる必要があります

Facebook Pluginの設定

Facebookでは、App IDとClient Tokenが必要です:

await SocialLogin.initialize({
  facebook: {
    appId: 'YOUR_FACEBOOK_APP_ID',        // From Facebook Developer Dashboard
    clientToken: 'YOUR_FACEBOOK_CLIENT_TOKEN', // From Facebook Developer Dashboard
    
    // Optional: Use Facebook Limited Login (for enhanced privacy)
    limitedLogin: false // See our Facebook setup guide for important Limited Login details
  }
});

Facebookに関する重要事項:

  • Supabaseで設定したものと同じApp IDを使用してください
  • Client TokenはFacebook AppのBasic Settingsにあります
  • limitedLogin: true Facebookのプライバシー重視のLimited Login機能を有効化(iOSのみ)
  • 重要:詳細は当社の Facebookの設定ガイド ATTに関する考慮事項を含む、詳細なLimited Loginの情報については

Reactアプリの起動時に@capgo/capacitor-social-loginを一度だけ初期化します

プラグインの初期化を完了する

すべてのプロバイダーをまとめて初期化する方法は以下の通りです:

import { SocialLogin } from '@capgo/capacitor-social-login';

export async function initializeSocialLogin() {
  await SocialLogin.initialize({
    google: {
      webClientId: 'YOUR_WEB_CLIENT_ID.apps.googleusercontent.com',
      mode: 'online'
    },
    facebook: {
      appId: 'YOUR_FACEBOOK_APP_ID',
      clientToken: 'YOUR_FACEBOOK_CLIENT_TOKEN',
    },
    apple: {
      // Prefer buildApplePluginConfig() from the React walkthrough.
      // Android: redirectUrl = Supabase apple-signin-callback Edge Function
      // Web: redirectUrl = window.location.href
    }
  });
}

重要な注意点:

  • 呼び出す initialize() 一度だけ ログインのたびではなく、アプリの起動時に
  • 使用する予定のプロバイダーのみを設定すればOKです
  • ここでの認証情報は以下から取得しています 元のプロバイダーSupabaseからではなく、
  • プロバイダーの認証情報がSupabaseの設定と一致していることを確認してください

ReactのSupabaseクライアントと認証レイヤー

まだSupabaseクライアントをインストールしていない場合は、以下を実行してください:

bun add @supabase/supabase-js

Reactツリー全体で共有する単一のクライアントを作成します:

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

const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY;

export const supabase = createClient(supabaseUrl, supabaseAnonKey, {
  auth: {
    autoRefreshToken: true,
    persistSession: true,
    detectSessionInUrl: false,
  },
});

Google + Supabase用のNonceヘルパー

Supabaseが要求するのは、 生のnonce における signInWithIdToken と、 SHA-256ダイジェスト をGoogleに渡すことです。 Supabase Google連携ガイド 一連の流れをドキュメント化しています。最小限のヘルパー:

// src/auth/nonce.ts
export function getUrlSafeNonce(): string {
  const array = new Uint8Array(32);
  crypto.getRandomValues(array);
  return Array.from(array, (byte) => byte.toString(16).padStart(2, '0')).join('');
}

export async function sha256Hex(message: string): Promise<string> {
  const data = new TextEncoder().encode(message);
  const hashBuffer = await crypto.subtle.digest('SHA-256', data);
  return Array.from(new Uint8Array(hashBuffer), (b) => b.toString(16).padStart(2, '0')).join('');
}

export async function createGoogleNoncePair(): Promise<{ rawNonce: string; nonceDigest: string }> {
  const rawNonce = getUrlSafeNonce();
  const nonceDigest = await sha256Hex(rawNonce);
  return { rawNonce, nonceDigest };
}

Social LoginとSupabaseを一つのモジュールに統合(〜のパターンを使用) 例 supabaseAuthUtils.ts):

// src/auth/socialLogin.ts
import { Capacitor } from '@capacitor/core';
import { SocialLogin } from '@capgo/capacitor-social-login';
import { supabase } from '../lib/supabaseClient';
import { createGoogleNoncePair } from './nonce';

export function isAppleLoginConfigured(): boolean {
  const platform = Capacitor.getPlatform();
  if (platform === 'ios') return true;
  const serviceId = import.meta.env.VITE_APPLE_SERVICE_ID;
  if (!serviceId) return false;
  if (platform === 'android') {
    return Boolean(import.meta.env.VITE_SUPABASE_APPLE_CALLBACK_URL);
  }
  if (platform === 'web') return true;
  return false;
}

function buildApplePluginConfig() {
  const platform = Capacitor.getPlatform();

  if (platform === 'ios') {
    return {};
  }

  if (platform === 'android') {
    return {
      clientId: import.meta.env.VITE_APPLE_SERVICE_ID,
      redirectUrl: import.meta.env.VITE_SUPABASE_APPLE_CALLBACK_URL,
    };
  }

  if (platform === 'web') {
    return {
      clientId: import.meta.env.VITE_APPLE_SERVICE_ID,
      redirectUrl: window.location.href,
    };
  }

  return {};
}

function isGoogleNonceMismatch(error: { message?: string }): boolean {
  return (error.message ?? '').toLowerCase().includes('nonce');
}

let initialization: Promise<void> | null = null;

export function ensureSocialLoginInitialized(): Promise<void> {
  if (!initialization) {
    const initOptions: Parameters<typeof SocialLogin.initialize>[0] = {
      google: {
        webClientId: import.meta.env.VITE_GOOGLE_WEB_CLIENT_ID,
        iOSClientId: import.meta.env.VITE_GOOGLE_IOS_CLIENT_ID,
        mode: 'online',
      },
    };

    if (isAppleLoginConfigured()) {
      initOptions.apple = buildApplePluginConfig();
    }

    initialization = SocialLogin.initialize(initOptions).catch((error) => {
      initialization = null;
      throw error;
    });
  }
  return initialization;
}

async function signInWithGoogleSupabaseOnce(allowNonceRetry: boolean) {
  await ensureSocialLoginInitialized();
  const { rawNonce, nonceDigest } = await createGoogleNoncePair();

  const result = await SocialLogin.login({
    provider: 'google',
    options: {
      scopes: ['email', 'profile'],
      nonce: nonceDigest,
    },
  });

  const googleResult = result.result;
  if (!googleResult || googleResult.responseType !== 'online' || !googleResult.idToken) {
    throw new Error('Google login did not return an ID token');
  }

  const { data, error } = await supabase.auth.signInWithIdToken({
    provider: 'google',
    token: googleResult.idToken,
    nonce: rawNonce,
  });

  if (error) {
    if (allowNonceRetry && isGoogleNonceMismatch(error)) {
      await SocialLogin.logout({ provider: 'google' });
      return signInWithGoogleSupabaseOnce(false);
    }
    throw error;
  }

  return data;
}

export async function signInWithGoogleSupabase() {
  return signInWithGoogleSupabaseOnce(true);
}

export async function signInWithAppleSupabase() {
  if (!isAppleLoginConfigured()) {
    throw new Error('Apple sign-in is not configured for this platform');
  }
  await ensureSocialLoginInitialized();
  const result = await SocialLogin.login({
    provider: 'apple',
    options: { scopes: ['email', 'name'] },
  });

  const appleIdToken = result.result?.idToken;
  if (!appleIdToken) throw new Error('Apple login did not return an idToken');

  const { data, error } = await supabase.auth.signInWithIdToken({
    provider: 'apple',
    token: appleIdToken,
  });

  if (error) throw error;
  return data;
}

export async function signOutEverywhere() {
  await supabase.auth.signOut();
  await Promise.all([
    SocialLogin.logout({ provider: 'google' }),
    SocialLogin.logout({ provider: 'apple' }),
  ]);
}

Apple initialize プラットフォーム別 ( Supabase Apple 共通, Android, Web):

  • iOSと: buildApplePluginConfig() を返します {}. Native Sign in with Apple では、bundle ID を使用します。No redirectUrl.
  • Android: clientId が Apple Service ID です。 redirectUrl は Supabase Edge Function (apple-signin-callback) です。関数をデプロイし、Apple Return URL にそのエンドポイントを設定し、アプリのディープリンク intent filter を追加して、フローが WebView に戻れるようにしてください (Android Supabase Apple ガイド).
  • Web: clientId が Service ID です。 redirectUrl が window.location.href、これは Apple Developer Portal の Return URL と一致している必要があります (Web Supabase Apple ガイド).

ensureSocialLoginInitialized() 以下を追加します: apple providerのみを指定する場合 isAppleLoginConfigured() がtrueの場合のみです。そのため、Googleのみの設定では、AndroidやWeb用の空のApple認証情報が渡されることはありません。

プラグインが返す値は result.idToken すべてのプラットフォームで共通です(AppleProviderResponse における @capgo/capacitor-social-login)。複数のプラットフォームでリリースする場合は、SupabaseにiOSのApp IDとService IDの両方を登録してください。

コンポーネントにセッション状態を公開:

// src/auth/useAuth.tsx
import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
  type ReactNode,
} from 'react';
import type { Session } from '@supabase/supabase-js';
import { supabase } from '../lib/supabaseClient';
import { ensureSocialLoginInitialized } from './socialLogin';

type AuthContextValue = {
  session: Session | null;
  loading: boolean;
  initError: string | null;
  clearInitError: () => void;
};

const AuthContext = createContext<AuthContextValue | null>(null);

export function AuthProvider({ children }: { children: ReactNode }) {
  const [session, setSession] = useState<Session | null>(null);
  const [loading, setLoading] = useState(true);
  const [initError, setInitError] = useState<string | null>(null);

  useEffect(() => {
    void ensureSocialLoginInitialized()
      .then(() => setInitError(null))
      .catch((error) => {
        setInitError(error instanceof Error ? error.message : 'Social login failed to initialize');
      });
    supabase.auth.getSession().then(({ data }) => {
      setSession(data.session);
      setLoading(false);
    });
    const { data: subscription } = supabase.auth.onAuthStateChange((_event, nextSession) => {
      setSession(nextSession);
    });
    return () => subscription.subscription.unsubscribe();
  }, []);

  const clearInitError = useCallback(() => setInitError(null), []);

  const value = useMemo(
    () => ({ session, loading, initError, clearInitError }),
    [session, loading, initError, clearInitError],
  );

  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}

export function useAuth() {
  const ctx = useContext(AuthContext);
  if (!ctx) throw new Error('useAuth must be used inside AuthProvider');
  return ctx;
}

ReactのログインUIと保護されたルート

モバイルレイアウトのGoogleおよびAppleボタン付きログイン画面サンプル

ログインパネル:

// src/components/LoginPanel.tsx
import { useState } from 'react';
import {
  isAppleLoginConfigured,
  signInWithAppleSupabase,
  signInWithGoogleSupabase,
} from '../auth/socialLogin';
import { useAuth } from '../auth/useAuth';

export function LoginPanel() {
  const { initError, clearInitError } = useAuth();
  const [error, setError] = useState<string | null>(null);
  const [busy, setBusy] = useState(false);
  const showApple = isAppleLoginConfigured();

  const run = async (action: () => Promise<unknown>) => {
    setBusy(true);
    setError(null);
    try {
      await action();
      clearInitError();
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Sign-in failed');
    } finally {
      setBusy(false);
    }
  };

  return (
    <div>
      <button type="button" disabled={busy} onClick={() => run(signInWithGoogleSupabase)}>
        Continue with Google
      </button>
      {showApple ? (
        <button type="button" disabled={busy} onClick={() => run(signInWithAppleSupabase)}>
          Continue with Apple
        </button>
      ) : null}
      {initError ? <p role="alert">{initError}</p> : null}
      {error ? <p role="alert">{error}</p> : null}
    </div>
  );
}

セッションのデバッグビュー(後で実際のユーザー用UIに置き換えてください):

// src/components/SessionDebug.tsx
import { useEffect, useState } from 'react';
import type { User } from '@supabase/supabase-js';
import { supabase } from '../lib/supabaseClient';
import { signOutEverywhere } from '../auth/socialLogin';

export function SessionDebug() {
  const [user, setUser] = useState<User | null>(null);

  useEffect(() => {
    supabase.auth.getUser().then(({ data }) => setUser(data.user));
  }, []);

  return (
    <div>
      <button type="button" onClick={() => signOutEverywhere()}>Sign out</button>
      <pre>{JSON.stringify(user, null, 2)}</pre>
    </div>
  );
}

Reactデバッグパネルに表示されたサインイン済みセッションのJSON

〜を使ったルート react-router-dom:

// src/App.tsx
import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
import { AuthProvider, useAuth } from './auth/useAuth';
import { LoginPanel } from './components/LoginPanel';
import { SessionDebug } from './components/SessionDebug';

function HomePage() {
  const { session, loading } = useAuth();
  if (loading) return <p>Loading…</p>;
  if (session) return <Navigate to="/account" replace />;
  return <LoginPanel />;
}

function AccountPage() {
  const { session, loading } = useAuth();
  if (loading) return <p>Loading…</p>;
  if (!session) return <Navigate to="/" replace />;
  return <SessionDebug />;
}

export default function App() {
  return (
    <AuthProvider>
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<HomePage />} />
          <Route path="/account" element={<AccountPage />} />
        </Routes>
      </BrowserRouter>
    </AuthProvider>
  );
}

アプリを〜にマウント main.tsx 通常どおり。プロバイダーへのログイン成功後、 onAuthStateChange アップデート session そして React Router がユーザーを〜へ遷移させます /account.

オプション: Facebook

Facebook も同様の signInWithIdToken プラグインのアクセストークンを使う同じパターンです。参照: Facebook のセットアップ および〜のプロバイダーブロック ステップ 4.

ReactアプリにCapacitorを追加する

Web bundleをビルドし、次にネイティブプロジェクトを追加します:

bun run build
bun add @capacitor/core @capacitor/cli @capacitor/ios @capacitor/android
bunx cap init "Capgo Auth Demo" com.example.authdemo --web-dir dist
bunx cap add ios
bunx cap add android

Capacitor がViteビルドをホストし、ネイティブSDKがソーシャルログインを処理します

Webビルドのたびに同期を実行:

bun run build
bunx cap sync

実機テストの準備ができたら、ネイティブIDEを開きます:

bunx cap open ios
bunx cap open android

実機でテストする前に、GoogleとAppleのプラットフォーム設定を完了させてください:

WebView内で呼び出す supabase.auth.signInWithOAuth チュートリアルには、多くの場合 Universal Links が必要です または App Links Googleによるリダイレクト後、OSがアプリに制御を戻します。Native Google によるサインインは、 IDトークン を使用することで、プラグインがブラウザでのOAuthラウンドトリップを行わないため、リダイレクトループを回避できます。 AndroidでのAppleログインは、 仕組みが異なります。Edge Functionのリダイレクトと、アプリの ディープリンク およびintent filterを使用するため、Appleログイン後にWebViewを再開できます。

他の機能(パスワードリセットメール、マジックリンク、マーケティング用URLなど)のためにdeep linkを設定する場合もあります。同じパスを以下に追加してください: 認証 > URL設定 Supabaseおよび apple-app-site-association / Androidのintent filterに、これらのフローを追加する際に設定します。

ステップ 8: プラットフォーム別の設定

iOSの設定

iOSの詳細なセットアップ手順については、以下のプラットフォーム別ガイドを参照してください:

クイックサマリー - 追加先 ios/App/App/Info.plist:

<!-- Google Sign-In URL scheme -->
<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>YOUR_REVERSED_CLIENT_ID</string>
    </array>
  </dict>
</array>

<!-- Apple Sign-In capability -->
<key>com.apple.developer.applesignin</key>
<array>
  <string>Default</string>
</array>

Xcodeプロジェクトの設定を含む、iOSの完全なセットアップ手順については、リンク先のガイドに従ってください。

Androidの設定

Androidの詳細なセットアップ手順については、以下のプラットフォーム別ガイドを参照してください:

必須の Android セットアップ:

1. SHA-1 フィンガープリントを取得 (Google の場合は必須):

# For debug builds (development)
cd android
./gradlew signingReport

# Look for the SHA1 fingerprint under "Variant: debug"
# Add this SHA1 to your Google Cloud Console Android OAuth client

2. AndroidManifest.xml の設定 - 以下を追加: android/app/src/main/AndroidManifest.xml:

<!-- Internet permission -->
<uses-permission android:name="android.permission.INTERNET" />

<!-- Facebook configuration -->
<meta-data 
  android:name="com.facebook.sdk.ApplicationId" 
  android:value="@string/facebook_app_id"/>
<meta-data 
  android:name="com.facebook.sdk.ClientToken" 
  android:value="@string/facebook_client_token"/>

3. Facebook リソースの追加 まで android/app/src/main/res/values/strings.xml:

<string name="facebook_app_id">YOUR_FACEBOOK_APP_ID</string>
<string name="facebook_client_token">YOUR_FACEBOOK_CLIENT_TOKEN</string>

Google Play Services の設定やパッケージ名の構成を含む、Android の完全な設定については、リンク先のプラットフォームガイドに従ってください。

ステップ 9: 認証済みユーザーによる Supabase データベースの利用

ユーザーが認証されると、Row Level Security (RLS) を適用した Supabase データベースを利用できます。

// Example: Fetch user profile
async function getUserProfile() {
  const { data: user } = await supabase.auth.getUser();
  
  if (user) {
    const { data, error } = await supabase
      .from('profiles')
      .select('*')
      .eq('id', user.user.id)
      .single();
    
    return data;
  }
}

// Example: Update user profile
async function updateUserProfile(updates: any) {
  const { data: user } = await supabase.auth.getUser();
  
  if (user) {
    const { data, error } = await supabase
      .from('profiles')
      .update(updates)
      .eq('id', user.user.id);
    
    return data;
  }
}

重要なセキュリティ上の考慮事項

  1. 機密性の高いキーを公開しない クライアント側の code に含めない
  2. 環境変数を利用する 設定管理には環境変数を使用
  3. Row Level Security を有効にする Supabase の RLS を設定
  4. トークンの検証を行う 必要に応じてバックエンドで検証
  5. トークンのリフレッシュ処理 Supabase で自動的にリフレッシュ

既知の問題とトラブルシューティング

Google での Nonce 不一致 (特に iOS)

Supabaseでnonceエラーが返る場合、GoogleがキャッシュされたIDトークンを返している可能性があります。プラグイン経由でGoogleからログアウトし、1回だけ再試行して、渡していることを確認してください nonceDigest まで SocialLogin.login と rawNonce まで signInWithIdToken。 サンプルアプリ 〜後の再試行 SocialLogin.logout.

トークンのaudienceエラー

すべてのGoogleクライアントID(web、iOS、Android)をSupabaseのGoogleプロバイダーに登録してください。 aud IDトークン内のclaimは、そのいずれかと一致している必要があります。

OAuthリダイレクトのチュートリアルとこのガイドの比較

〜を使っているブログ記事 signInWithOAuth WebViewでのリダイレクトがアプリではなくSafariで開いてしまうと、モバイルでは失敗することがあります。ネイティブログイン、または signInWithIdToken Capacitorにはこちらを、あるいは Social LoginのWebセットアップを ブラウザのリダイレクトに利用してください。

プラットフォーム別の確認事項

トークンの不一致とネットワークエラー

  • Google Cloud、Supabase、および SocialLogin.initialize
  • Reactでのローディングとエラー状態の表示(上記 LoginPanel を参照)

まとめ

これで、Supabaseの堅牢なバックエンドとネイティブなソーシャルログインを組み合わせた、完全な認証システムが整いました。この構成により、以下が可能になります:

  • 安全なネイティブ・ソーシャル認証
  • シームレスなトークン管理
  • リアルタイムなデータベース連携
  • クロスプラットフォーム対応

SupabaseとCapgo Social Loginプラグインを組み合わせることで、Capacitorアプリに強力でスケーラブルな認証ソリューションを提供できます。

次のような高度な機能については: 多要素認証(MFA)を または カスタムクレーム、以下を確認してください: Supabase ドキュメント および Social Login プラグインのドキュメント.

Capacitor Social Login プラグインを使用した Supabase Authentication のセットアップから先に進む

使用している場合 Capacitor Social Login プラグインを使用した Supabase Authentication のセットアップ 認証とアカウントフローを計画するには、これを次と連携させてください @capgo/capacitor-social-login @capgo/capacitor-social-login の実装の詳細については、 @capgo/capacitor-passkey @capgo/capacitor-passkey の実装詳細については、 @capgo/capacitor-native-biometric @capgo/capacitor-native-biometric の実装の詳細については、 2要素認証 二要素認証の実装の詳細については、また、 SSO (エンタープライズ) SSO (Enterprise) の実装の詳細については。

Capacitor アプリ向けの Live Updates

Web レイヤーのバグが本番で発生したら、App Store の審査を何日も待たずに Capgo で修正を配信しましょう。ネイティブの変更は通常の審査フローに残したまま、ユーザーはバックグラウンドでアップデートを受け取れます。

最新のブログ記事

Capgoは、真にプロフェッショナルなモバイルアプリを作るために必要な最高のインサイトを提供します。