Zum Hauptinhalt springen
Tutorials

Capacitor, Supabase und Social Auth in React

Schritt-für-Schritt-Tutorial zu React und Capacitor für Supabase-Authentifizierung mit @capgo/capacitor-social-login. Native Google- und Apple-Sign-in, nonce-sicherem signInWithIdToken und einer Vite-App, die du auf Mobile ausliefern kannst.

Capacitor, Supabase und Social Auth in React

Native Google- und Apple-Sign-in in einer React App implementieren, unterstützt durch Supabase Auth, und kapselt dieselbe UI in Capacitor ohne Probleme mit Mobile-Browser-Redirects. Capgo Social Login (@capgo/capacitor-social-login) übernimmt die nativen Provider-Sheets; du tauschst den Provider-ID-Token gegen eine Supabase-Session mit signInWithIdToken.

Dieser Artikel erweitert unseren bestehenden Supabase + Social Login Guide um ein vollständiges React + Vite Walkthrough (Projektstruktur, Provider, Routes, Capacitor Wiring). Für Provider-Dashboards und Platform-Keys nutze weiterhin die Supabase Integration Docs und Google + Supabase Setup. Ähnliche Beiträge: Google Sign-in mit Capacitor, Apple Sign-in mit Capacitor, und Authentifizierungsoptionen in Capacitor.

Inhaltsverzeichnis

Das wirst du bauen

  • Ein Vite + React + TypeScript Web-App mit Login-Buttons und einer Debug-Ansicht für angemeldete Nutzer
  • Supabase Auth Sessions aus Native erstellt Google (und optional Apple) ID-Tokens
  • Derselbe Bundle, der läuft in Capacitor auf iOS und Android
  • Ein nonce-sicherer Google-Flow passend zum Plugin-Beispiel-App

Gesamter Authentifizierungs-Flow

Mit @capgo/capacitor-social-login, führt die Mobile App aus es nicht verlassen auf signInWithOAuth Redirects innerhalb der WebView. Das native SDK liefert einen ID-Token; Supabase validiert diesen und stellt ein eigenes JWT aus.

Flow von der React UI über Capgo Social Login und Google zu Supabase Auth

An Web, kannst du weiterhin dasselbe Plugin nutzen (siehe Google Web-Setup). Behandle alle OAuth-Return-URLs in deinem Router, falls du später einen Browser-Fallback hinzufügst.

Basis React (Vite) Anwendung

Erstelle eine neue App (oder nutze eine bestehende React-Codebase):

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

Starte den Dev-Server:

bun run dev

Lokaler Vite-Dev-Server nach der Installation von Supabase und Social Login

Ziel-Ordnerstruktur:

Empfohlene src-Struktur für Supabase Auth-Helper und React-Pages

Umgebungsvariablen eintragen in .env.local (Secrets niemals committen):

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

Warum Supabase mit Social Login nutzen?

Supabase bietet ein robustes Backend-as-a-Service mit integrierter Authentifizierung, während das @capgo/capacitor-social-login Plugin native Social Authentication für iOS, Android und Web bietet. Für eine engere Supabase-Integration, @capgo/capacitor-supabase bietet native Auth-Helper und JWT-Zugriff. Zusammen ermöglichen sie:

  • Nahtlose Social Authentication
  • Sicheres Token-Management
  • Cross-Platform-Kompatibilität
  • Echtzeit-Datenbank-Integration
  • Integriertes User-Management

Voraussetzungen

Before starting, ensure you have:

  • Ein aufgesetztes Capacitor Projekt
  • Ein Supabase-Konto und ein Projekt
  • Developer-Accounts für deine gewählten Social Provider (Google, Apple, Facebook)

Schritt 1: Social Login Plugin installieren und konfigurieren

Installiere zuerst das Capgo Social Login Plugin:

bun add @capgo/capacitor-social-login

Ausführen bunx cap sync danach du fügst Capacitor und native Plattformen in Füge Capacitor der React-App hinzu. Die untenstehende Vite-Anleitung funktioniert vor diesem Schritt im Browser.

Siehe den Social Login und Supabase Plugin-Seiten für die plattformspezifische Einrichtung.

Schritt 2: Supabase-Projekt einrichten

Supabase-Dashboard-Checkliste zum Aktivieren der Google-Anmeldung mit ID-Token

Erstelle und konfiguriere dein Supabase-Projekt

  1. Erstelle ein Supabase-Projekt:

    • Gehe zu supabase.com und registriere dich bzw. melde dich an
    • Klicken „New Project“
    • Wähle deine Organisation
    • Gib einen Projektnamen ein (z. B. „MyApp Auth“)
    • Lege einen Datenbank-Passwort (sicher aufbewahren)
    • Wähle deine Region (die nächstgelegene zu deinen Usern wählen)
    • Klicken „Neues Projekt erstellen“
  2. Projekt-Credentials abrufen:

    • Nach dem Erstellen gehe zu Einstellungen > API
    • Kopiere deine Projekt-URL (z. B. https://your-project-ref.supabase.co)
    • Kopiere deine anon public API Key
    • Save these for later use in your app

Authentication-Einstellungen konfigurieren

  1. Allgemeine Authentication-Einstellungen einrichten:

    • Gehe zu Authentifizierung > Einstellungen
    • Unter Allgemeine Einstellungen:
      • Setzen Sie Website-URL zur URL deiner App (z. B. https://yourdomain.com oder http://localhost:3000 für die Entwicklung)
      • Zusätzlich hinzufügen, Redirect-URLs falls nötig:
        http://localhost:3000
        https://yourdomain.com
        capacitor://localhost (for mobile apps)
  2. E-Mail-Einstellungen konfigurieren (optional, aber empfohlen):

    • Unter SMTP-Einstellungen, konfiguriere deinen E-Mail-Anbieter
    • Dies ermöglicht E-Mail-Bestätigungen und Passwort-Resets
    • Für die Entwicklung kannst du den integrierten E-Mail-Service nutzen

Social Authentication Provider aktivieren

  1. Navigiere zum Bereich Providers:
    • Gehe zu Authentifizierung > Provider in deinem Supabase Dashboard
    • Du siehst eine Liste der verfügbaren Social Provider
    • Jeder Provider hat einen Aktivieren Toggle- und Konfigurationsoptionen

Konfigurieren wir nun die einzelnen Social Provider im Detail:

Schritt 3: Social Provider in Supabase konfigurieren

Google Authentication in Supabase einrichten

Besorge zuerst deine Google OAuth-Credentials:

Folge unserer ausführlichen Google-Setup-Anleitung: Google Authentication Setup

Diese Anleitung umfasst:

  • Erstellen eines Google Cloud Projekts
  • Einrichten von OAuth 2.0 Credentials für Web, iOS und Android
  • Konfigurieren des Consent Screens
  • Abrufen der benötigten Client IDs und Secrets

Nach dem Google-Setup erfolgt die Konfiguration in Supabase:

Folge dem Supabase + Google Leitfaden für Screenshots der Dashboards hier klicken.

  1. Google Provider in Supabase aktivieren:
    • Gehe in deinem Supabase Dashboard zu Authentifizierung > Provider
    • Finde Google und aktiviere ihn AN
    • Füge den Web, iOS, und Android Client-IDs aus der Google Cloud (Plattformen, die du nicht nutzt, überspringen)
    • Klicken Speichern

Wichtig für dieses React-Tutorial: when you use signInWithIdToken mit @capgo/capacitor-social-login, machst du es nicht OAuth-Daten benötigen Client Secret oder die Callback-URL-Felder für Google. Registriere alle Client-IDs, die Supabase bei der Validierung der Token von jeder Plattform akzeptiert.

Apple Authentication in Supabase einrichten

Apple-Zugangsdaten abrufen:

Folge unserer detaillierten Apple-Setup-Anleitung: Apple Authentication Setup

Diese Anleitung umfasst:

  • Einrichtung deines Apple Developer Accounts
  • Erstellen von App IDs und Service IDs
  • Konfigurieren der Sign in with Apple Capability
  • Generieren der erforderlichen Private Keys
  • Plattformspezifisches Setup für iOS, Android und Web

Nach dem Apple-Setup in Supabase konfigurieren:

  1. Apple Provider in Supabase aktivieren:
    • Gehe zu Authentication > Providers und umschalten Apple AN
    • Konfiguration ausfüllen:
      • Client-ID: Deine iOS App ID und Apple Service ID (bei Multi-Plattform-Support), durch Komma getrennt (z. B. com.yourapp,com.yourapp.signin). iOS-Tokens nutzen die App ID Audience; Android und Web nutzen die Service ID. Siehe Supabase Apple Allgemeines.
      • Für den Ablauf signInWithIdToken dieses Tutorials @capgo/capacitor-social-loginmusst du es nicht ein OAuth Client Secret oder eine Supabase OAuth Callback URL im Apple Provider Formular angeben.
    • Klicken Speichern

Hinweis: Das Apple Authentication Setup ist aufgrund der Anforderungen an Service IDs, Private Keys und plattformspezifische Redirect URLs am komplexesten. Folge unserer Dokumentation für jede Plattform genau.

Facebook Authentication in Supabase einrichten

Facebook-Credentials abrufen:

Folge unserer Anleitung zum Facebook-Setup: Facebook Authentication Setup

Diese Anleitung umfasst:

  • Erstellen eines Facebook Developer Accounts und einer App
  • Hinzufügen des Facebook Login Produkts
  • Konfigurieren der OAuth Redirect URIs
  • Abrufen von App ID, App Secret und Client Token
  • Plattformspezifische Konfiguration für iOS und Android

Nach dem Facebook-Setup erfolgt die Konfiguration in Supabase:

  1. Facebook Provider in Supabase aktivieren:
    • Gehe zu Authentifizierung > Provider und umschalten Facebook AN
    • Konfiguration ausfüllen:
      • Client-ID: Deine Facebook App ID
      • Client Secret: Dein Facebook App Secret
      • Redirect-URL: https://your-project-ref.supabase.co/auth/v1/callback (auto-filled)
    • Klicken „Speichern“

Wichtig: Stelle sicher, dass du die Supabase Callback-URL (https://your-project-ref.supabase.co/auth/v1/callback) in deiner Facebook-App zu den Gültige OAuth-Redirect-URIs in den Facebook Login-Einstellungen hinzufügst.

Wichtige Hinweise zur Supabase-Konfiguration

Row Level Security (RLS):

  • Nach der Einrichtung der Authentifizierung aktiviere RLS für deine Tabellen unter
  • Gehe zu Datenbank > Tabellen und umschalten RLS aktivieren für jede Tabelle
  • Erstelle Policies, um den Datenzugriff basierend auf authentifizierten Usern zu steuern

Benutzerverwaltung:

  • Authentifizierte User anzeigen unter Authentifizierung > Benutzer
  • Auth-Events überwachen unter Authentifizierung > Logs
  • Email-Templates einrichten unter Authentifizierung > E-Mail-Vorlagen

Konfiguration testen:

  • Nutze das integrierte Auth-Testtool von Supabase
  • Gehe zu Authentifizierung > Nutzer und klicke auf „Nutzer einladen“ um E-Mail-Flows zu testen
  • Schau in die Logs Abschnitt für Authentifizierungsfehler

Schritt 4: Social Login Plugin konfigurieren

Nachdem Supabase konfiguriert ist, musst du das Social Login Plugin mit den entsprechenden Credentials einrichten. Wichtig: Das Plugin benötigt die OAuth-Credentials von den ursprünglichen Providern (nicht von Supabase), während Supabase die serverseitige Authentifizierung übernimmt.

So funktioniert der Authentication Flow

Bevor du mit der Konfiguration startest, hier der Ablauf:

  1. Plugin authentifiziert nativ beim Social Provider (Google/Apple/Facebook)
  2. Plugin erhält Tokens (Access Token, ID Token) vom Provider
  3. Deine App sendet diese Tokens an Supabase mit signInWithIdToken()
  4. Supabase validiert die Tokens beim Provider und erstellt eine User Session
  5. Supabase gibt zurück einen eigenen JWT-Token für die authentifizierten Requests deiner App

Google Plugin Konfiguration

Das Plugin benötigt deine Web-Client-ID für alle Plattformen und optional eine iOS Client-ID für iOS-spezifische Features:

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'
  }
});

Wichtige Punkte für Google:

  • Nutze das Web-Client-ID (keine Android/iOS Client IDs) für das webClientId Feld
  • Das Plugin funktioniert auf allen Plattformen nur mit der Web Client ID
  • Der iOSClientId ist optional und wird nur für iOS-spezifische Google-Features genutzt

Apple Plugin Konfiguration

Die Apple-Konfiguration unterscheidet sich zwischen iOS und Android:

Für iOS (natives Apple Sign-In):

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

Für Android/Web (erfordert Service ID). Nutze dieselben Redirect-Regeln wie buildApplePluginConfig() im React-Tutorial:

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,
        },
});

Wichtige Punkte für Apple:

  • iOS nutzt natives Sign in with Apple (keine extra Config nötig)
  • Android nutzt deine Service ID und die Supabase apple-signin-callback Edge Function URL
  • Web nutzt deine Service ID und window.location.href, die mit den Apple Return URLs übereinstimmen muss

Facebook Plugin Konfiguration

Facebook benötigt deine App ID und den 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
  }
});

Wichtige Punkte für Facebook:

  • Nutze dieselbe App ID, die du in Supabase konfiguriert hast
  • Den Client Token findest du in den Basic Settings deiner Facebook App
  • limitedLogin: true aktiviert Facebooks datenschutzorientiertes Limited Login Feature (nur iOS)
  • Wichtig: Siehe unsere Facebook Setup-Guide für Details zum Limited Login, inkl. ATT-Aspekten

Initialisiere @capgo/capacitor-social-login einmal beim Start der React-App

Plugin-Initialisierung abschließen

So initialisierst du alle Provider gleichzeitig:

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
    }
  });
}

Wichtige Hinweise:

  • Rufe initialize() einmal beim App-Start, nicht vor jedem Login
  • Du musst nur die Provider konfigurieren, die du nutzen willst
  • Die Credentials stammen von den originalen Providern, nicht von Supabase
  • Stelle sicher, dass die Provider-Credentials mit deiner Supabase-Konfiguration übereinstimmen

React Supabase Client und Auth-Layer

Installiere den Supabase Client, falls noch nicht geschehen:

bun add @supabase/supabase-js

Erstelle einen einzelnen Client für den gesamten React-Tree:

// 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,
  },
});

Nonce-Helper für Google + Supabase

Supabase erwartet einen rohen Nonce in signInWithIdToken und einen SHA-256 Digest an Google übergeben. Der Supabase Google Guide dokumentiert den gesamten Flow. Minimale Helfer:

// 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 in einem Modul verbinden (Pattern aus dem Beispiel) 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 pro Plattform (siehe Supabase Apple Allgemein, Android, Web):

  • iOS: buildApplePluginConfig() gibt zurück {}. Native Sign in with Apple nutzt deine Bundle ID. Keine redirectUrl.
  • Android: clientId ist deine Apple Service ID. redirectUrl ist deine Supabase Edge Function (apple-signin-callback). Deploy die Function, setze die Apple Return URL auf diesen Endpoint und füge den App Deep Link Intent Filter hinzu, damit der Flow zur WebView zurückkehren kann (Android Supabase Apple Guide).
  • Web: clientId ist deine Service ID. redirectUrl ist window.location.href, die mit einer Return URL im Apple Developer Portal übereinstimmen muss (Web Supabase Apple Guide).

ensureSocialLoginInitialized() fügt den apple Provider nur, wenn isAppleLoginConfigured() wahr ist; so übergibt ein reines Google-Setup keine leeren Android- oder Apple-Web-Credentials.

Das Plugin gibt result.idToken auf allen Plattformen zurück (AppleProviderResponse in @capgo/capacitor-social-login). Registriere sowohl die iOS App ID als auch die Service ID in Supabase, wenn du mehrere Plattformen veröffentlichst.

Session-Status für Komponenten bereitstellen:

// 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-Login-UI und geschützte Routen

Beispielhafter Login-Screen mit Google- und Apple-Buttons in einem mobilen Layout

Login-Panel:

// 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>
  );
}

Session-Debug-View (später durch dein echtes Account-UI ersetzen):

// 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>
  );
}

Angemeldete Session als JSON in einem React-Debug-Panel

Routes mit 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>
  );
}

Mount the app in main.tsx wie gewohnt. Nach dem erfolgreichen Login beim Provider onAuthStateChange Updates session und React Router leitet den User zu /account.

Optional: Facebook

Facebook folgt demselben signInWithIdToken Pattern mit dem Access Token aus dem Plugin. Siehe Facebook Setup und dem Provider-Block in Schritt 4.

Füge Capacitor der React-App hinzu

Web-Bundle erstellen und dann native Projekte hinzufügen:

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 hostet den Vite-Build, während die nativen SDKs das Social Login übernehmen

Nach jedem Web-Build synchronisieren:

bun run build
bunx cap sync

Öffne die native IDE, wenn du bereit bist, auf Geräten zu testen:

bunx cap open ios
bunx cap open android

Schließe die Schritte für Google und Apple ab, bevor du auf Hardware testest:

Tutorials, die innerhalb supabase.auth.signInWithOAuth eines WebViews aufgerufen werden, benötigen oft Universal Links oder App-Links damit das OS nach dem Google-Redirect die Kontrolle an die App zurückgibt. Native Google Sign-in mit einem ID-Token verhindert diesen Redirect-Loop, da das Plugin keinen Browser-OAuth-Roundtrip öffnet. Apple auf Android funktioniert anders: Es nutzt weiterhin den Edge Function Redirect und einen App- Deep Link Intent Filter, damit die WebView nach dem Apple-Login fortfahren kann.

Du kannst Deep Links weiterhin für andere Features konfigurieren (Passwort-Reset-Mails, Magic Links, Marketing-URLs). Füge dieselben Pfade zu Authentifizierung > URL-Konfiguration in Supabase und für deine apple-app-site-association / Android Intent-Filter, wenn du diese Flows hinzufügst.

Schritt 8: Plattformspezifische Konfiguration

iOS-Konfiguration

Detaillierte iOS-Setup-Anleitungen findest du in unseren plattformspezifischen Guides:

Kurzzusammenfassung - Hinzufügen zu 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>

Folge den verlinkten Guides für die vollständige iOS-Einrichtung inklusive Xcode-Projektkonfiguration.

Android-Konfiguration

Detaillierte Anleitungen zur Android-Einrichtung findest du in unseren plattformspezifischen Guides:

Wichtige Android-Konfiguration:

1. SHA-1-Fingerprint ermitteln (erforderlich für 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 konfigurieren - Hinzufügen zu 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-Ressourcen hinzufügen zu 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>

Folge den verlinkten Plattform-Guides für die vollständige Android-Konfiguration, einschließlich der Einrichtung der Google Play Services und der Konfiguration des Package-Namens.

Schritt 9: Supabase-Datenbank mit authentifizierten Usern nutzen

Sobald die User authentifiziert sind, kannst du die Supabase-Datenbank mit Row Level Security (RLS) nutzen:

// 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;
  }
}

Wichtige Sicherheitsaspekte

  1. Gib niemals sensible Keys preis in deinem Client code
  2. Nutze Umgebungsvariablen für die Konfiguration
  3. Aktiviere Row Level Security in Supabase
  4. Token validieren bei Bedarf im Backend
  5. Token-Refresh handhaben automatisch mit Supabase

Bekannte Probleme und Troubleshooting

Nonce-Mismatch bei Google (besonders iOS)

Falls Supabase einen Nonce-Fehler zurückgibt, hat Google eventuell ein gecachtes ID-Token gesendet. Logge dich über das Plugin bei Google aus, versuche es erneut und stelle sicher, dass du die nonceDigest zu SocialLogin.login und rawNonce zu signInWithIdToken. Die Beispiel-App Wiederholungsversuche nach SocialLogin.logout.

Token-Audience-Fehler

Registriere jede Google Client ID (Web, iOS, Android) im Supabase Google Provider. Der aud Claim im ID-Token muss mit einer davon übereinstimmen.

OAuth-Redirect-Tutorials vs. dieser Guide

Blog posts that use signInWithOAuth in einer WebView auf Mobilgeräten fehlschlagen, wenn der Redirect Safari statt deiner App öffnet. Nutze lieber natives Login + signInWithIdToken für Capacitor, oder folge der Social Login Web-Konfiguration für Browser-Redirects.

Plattformspezifische Checks

Token-Mismatch und Netzwerkfehler

  • Provider-Credentials in Google Cloud, Supabase und SocialLogin.initialize
  • Loading- und Error-States in React (siehe LoginPanel oben)

Fazit

Du hast nun ein vollständiges Authentifizierungssystem, das das robuste Backend von Supabase mit nativen Social-Login-Funktionen kombiniert. Dieses Setup bietet:

  • Sichere, native Social-Authentifizierung
  • Nahtloses Token-Management
  • Echtzeit-Datenbankintegration
  • Plattformübergreifende Kompatibilität

Die Kombination aus Supabase und dem Capgo Social Login Plugin bietet eine leistungsstarke, skalierbare Authentifizierungslösung für deine Capacitor Apps.

Für fortgeschrittene Features wie Multi-Faktor-Authentifizierung oder Custom Claims, schau dir die Supabase-Dokumentation an und Social Login Plugin-Dokumentation.

Weiterlesen: Supabase Authentication mit dem Capacitor Social Login Plugin einrichten

Wenn du es nutzt Supabase Authentication mit dem Capacitor Social Login Plugin einrichten Um Authentifizierungs- und Account-Flows zu planen, verbinde es mit @capgo/capacitor-social-login für die Implementierungsdetails in @capgo/capacitor-social-login, @capgo/capacitor-passkey für die Implementierungsdetails in @capgo/capacitor-passkey, @capgo/capacitor-native-biometric für die Implementierungsdetails in @capgo/capacitor-native-biometric, Zwei-Faktor-Authentifizierung für die Implementierungsdetails zur Zwei-Faktor-Authentifizierung, und SSO (Enterprise) für die Implementierungsdetails zu SSO (Enterprise).

Live-Updates für Capacitor-Apps

Wenn ein Bug im Web-Layer live ist, liefere den Fix über Capgo aus, statt Tage auf die App-Store-Freigabe zu warten. Nutzer bekommen das Update im Hintergrund, während native Änderungen im normalen Review-Prozess bleiben.

Neues aus unserem Blog

Capgo gibt dir die besten Insights, um eine wirklich professionelle Mobile App zu erstellen.