Saltar al contenido principal
Tutorial

Capacitor, Supabase y Social Auth en React

Tutorial paso a paso de React y Capacitor para autenticación con Supabase usando @capgo/capacitor-social-login. Native Google y Apple sign-in, signInWithIdToken seguro con nonce y una app de Vite lista para móvil.

Capacitor, Supabase y Social Auth en React

Lanza el inicio de sesión nativo de Google y Apple en una React app, respaldada por Autenticación de Supabase, y envuelve la misma UI en Capacitor sin lidiar con redirecciones del navegador móvil. Social Login con Capgo (@capgo/capacitor-social-login) gestiona las hojas nativas del proveedor; intercambias el ID token del proveedor por una sesión de Supabase con signInWithIdToken.

Este artículo amplía nuestra guía de Supabase + Social Login con un React + Vite tutorial completo (estructura del proyecto, providers, rutas, configuración de Capacitor). Para dashboards de proveedores y keys de plataforma, sigue usando la documentación de integración de Supabase y la configuración general de Google + Supabase. Posts relacionados: Inicio de sesión con Google usando Capacitor, Inicio de sesión con Apple usando Capacitor, y opciones de autenticación en Capacitor.

Tabla de contenidos

Qué vas a construir

  • Una Vite + React + TypeScript web app con botones de sign-in y vista de debug
  • Autenticación de Supabase sesiones creadas desde native Google (y opcional Apple) tokens ID
  • El mismo bundle ejecutándose en Capacitor en iOS y Android
  • Un flujo de Google seguro contra nonce, alineado con el app de ejemplo del plugin

Flujo de autenticación general

Con @capgo/capacitor-social-login, la app móvil realiza necesitas confiar en signInWithOAuth redirecciones dentro del WebView. El SDK nativo devuelve un Token de ID; Supabase lo valida y emite su propio JWT.

Flujo desde la UI de React mediante Capgo Social Login y Google hacia Supabase Auth

En web, puedes seguir usando el mismo plugin (ver configuración web de Google). Gestiona las URLs de retorno de OAuth en tu router si más adelante añades un fallback de navegador.

Aplicación base en React (Vite)

Crea una app nueva (o reutiliza un codebase de 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

Inicia el servidor de dev:

bun run dev

Servidor de dev local de Vite tras instalar Supabase y Social Login

Estructura de carpetas objetivo:

Estructura de src sugerida para helpers de auth de Supabase y páginas de React

Añade las variables de entorno en .env.local (nunca hagas commit de secrets):

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

¿Por qué usar Supabase con Social Login?

Supabase ofrece un backend-as-a-service robusto con autenticación integrada, mientras que el @capgo/capacitor-social-login plugin ofrece autenticación social nativa en iOS, Android y web. Para una integración más estrecha con Supabase, @capgo/capacitor-supabase añade helpers de auth nativa y acceso JWT. Juntos, ofrecen:

  • Autenticación social fluida
  • Gestión segura de tokens
  • Compatibilidad multiplataforma
  • Integración de base de datos en tiempo real
  • Gestión de usuarios integrada

Requisitos

Antes de empezar, asegúrate de tener:

  • Un proyecto Capacitor configurado
  • Una cuenta y proyecto de Supabase
  • Cuentas de desarrollador para tus proveedores sociales (Google, Apple, Facebook)

Paso 1: Instalar y configurar el plugin de Social Login

Primero, instala el plugin de Capgo Social Login:

bun add @capgo/capacitor-social-login

Ejecuta bunx cap sync después de añades Capacitor y las plataformas nativas en Añade Capacitor a la app de React. El tutorial solo para Vite funciona en el navegador antes de ese paso.

Consulta la Social Login y Supabase plugin pages for platform-specific setup.

Paso 2: Configurar el proyecto de Supabase

Checklist del dashboard de Supabase para habilitar Google con ID token

Crea y configura tu proyecto de Supabase

  1. Crea un proyecto en Supabase:

    • Ve a supabase.com y regístrate o inicia sesión
    • Haz clic “Nuevo proyecto”
    • Elige tu organización
    • Introduce un Nombre del proyecto (ej., “MyApp Auth”)
    • Configura un Contraseña de la base de datos (guárdala de forma segura)
    • Selecciona tu Región (elige la más cercana a tus usuarios)
    • Haz clic “Crear nuevo proyecto”
  2. Obtén las credenciales de tu proyecto:

    • Una vez creado, ve a Configuración > API
    • Copia tu URL del proyecto (ej., https://your-project-ref.supabase.co)
    • Copia tu anon public clave de API
    • Guárdalos para usarlos después en tu app

Configurar ajustes de autenticación

  1. Configura los ajustes generales de autenticación:

    • Ve a Autenticación > Configuración
    • En Configuración general:
      • Configurar URL del sitio a la URL de tu app (ej., https://yourdomain.com o http://localhost:3000 para desarrollo)
      • Añadir otras URLs de redirección si es necesario:
        http://localhost:3000
        https://yourdomain.com
        capacitor://localhost (for mobile apps)
  2. Configurar ajustes de email (opcional pero recomendado):

    • En Configuración SMTP, configura tu proveedor de email
    • Esto permite confirmaciones por email y restablecimiento de contraseñas
    • Para desarrollo, puedes usar el servicio de email integrado

Habilitar proveedores de autenticación social

  1. Accede a la sección de proveedores:
    • Ve a Autenticación > Proveedores en tu dashboard de Supabase
    • Verás una lista de proveedores sociales disponibles
    • Cada proveedor tiene un Activar opciones de configuración y toggle

Ahora configuremos cada proveedor social en detalle:

Paso 3: Configurar proveedores sociales en Supabase

Configuración de Google Authentication en Supabase

Primero, obtén tus credenciales de Google OAuth:

Sigue nuestra guía completa de configuración de Google: Configuración de Google Authentication

Esta guía cubre:

  • Creación de un proyecto en Google Cloud
  • Configuración de credenciales OAuth 2.0 para web, iOS y Android
  • Configuración de la pantalla de consentimiento
  • Obtención de los Client IDs y secrets necesarios

Tras completar la configuración de Google, configúralo en Supabase:

Sigue la Guía general de Supabase + Google para ver capturas de cada dashboard.

  1. Habilita el proveedor de Google en Supabase:
    • En tu dashboard de Supabase, ve a Autenticación > Proveedores
    • Busca Google y actívalo ON
    • Añade la Web, iOS, y Android client IDs que creaste en Google Cloud (omite las plataformas que no publiques)
    • Haz clic Guardar

Importante para este tutorial de React: cuando usas signInWithIdToken con @capgo/capacitor-social-login, sí necesitas necesitas necesitas los campos OAuth secret del cliente o callback URL para Google. Registra todos los client IDs que Supabase aceptará al validar los tokens de cada plataforma.

Configuración de Apple Authentication en Supabase

Obtén las credenciales de Apple:

Sigue nuestra guía detallada para configurar Apple: Configuración de Apple Authentication

Esta guía cubre:

  • Configuración de tu cuenta de Apple Developer
  • Creación de App IDs y Service IDs
  • Configuración de la capacidad Sign in with Apple
  • Generación de las private keys necesarias
  • Configuración por plataforma para iOS, Android y Web

Tras completar la configuración de Apple, configúralo en Supabase:

  1. Habilitar el proveedor Apple en Supabase:
    • Ve a Autenticación > Proveedores y activa Apple ON
    • Completa la configuración:
      • ID de cliente: Tu iOS App ID y tu Apple Service ID cuando lances ambas plataformas, separados por comas (por ejemplo com.yourapp,com.yourapp.signin). Los tokens de iOS usan el App ID como audience; Android y web usan el Service ID. Consulta Configuración general de Supabase con Apple.
      • Para el flujo de este tutorial signInWithIdToken con Apple @capgo/capacitor-social-login, sí necesitas necesitas un client secret de OAuth o la URL de callback de Supabase OAuth en el formulario del proveedor de Apple.
    • Haz clic Guardar

Nota: La configuración de la autenticación de Apple es la más compleja debido a los requisitos de Apple para Service IDs, claves privadas y URLs de redirección específicas de cada plataforma. Sigue nuestra documentación con cuidado para cada plataforma.

Configurar la autenticación de Facebook en Supabase

Obtén las credenciales de Facebook:

Sigue nuestra guía completa para configurar Facebook: Configuración de la autenticación con Facebook

Esta guía cubre:

  • Crear una cuenta de desarrollador de Facebook y una app
  • Añadir el producto Facebook Login
  • Configurar las URIs de redirección OAuth
  • Obtener tu App ID, App Secret y Client Token
  • Configuración específica de plataforma para iOS y Android

Después de completar la configuración de Facebook, configúrala en Supabase:

  1. Habilitar el proveedor de Facebook en Supabase:
    • Ve a Autenticación > Proveedores y activa Facebook ACTIVADO
    • Completa la configuración:
      • ID de cliente: Tu Facebook App ID
      • Secreto del cliente: Tu Facebook App Secret
      • URL de redirección: https://your-project-ref.supabase.co/auth/v1/callback (autocompletado)
    • Haz clic “Guardar”

Importante: Asegúrate de añadir la URL de callback de Supabase (https://your-project-ref.supabase.co/auth/v1/callback) a tu app de Facebook URI de redireccionamiento de OAuth válidos en la configuración de Facebook Login.

Notas importantes de configuración de Supabase

Seguridad a nivel de fila (RLS):

  • Después de configurar la autenticación, activa RLS en tus tablas
  • Ve a Database > Tables y activa Habilitar RLS para cada tabla
  • Crea políticas para controlar el acceso a los datos según los usuarios autenticados

Gestión de usuarios:

  • Ver usuarios autenticados en Autenticación > Usuarios
  • Monitorea eventos de autenticación en Autenticación > Logs
  • Configura plantillas de email en Autenticación > Plantillas de correo electrónico

Prueba la configuración:

  • Usa la herramienta de test de autenticación de Supabase
  • Ve a Autenticación > Usuarios y haz clic en “Invitar usuario” para probar flujos de email
  • Consulta la Logs sección para errores de autenticación

Paso 4: Configurar el plugin de Social Login

Con Supabase configurado, ahora debes preparar el plugin de Social Login con las credenciales correspondientes. Importante: El plugin requiere las credenciales OAuth de los proveedores originales (no desde Supabase), mientras Supabase gestiona la autenticación en el servidor.

Cómo funciona el flujo de autenticación

Antes de configurar, entiende el flujo:

  1. El plugin autentica con el proveedor social (Google/Apple/Facebook) de forma nativa
  2. El plugin recibe los tokens (access token, ID token) del proveedor
  3. Tu app envía estos tokens a Supabase usando signInWithIdToken()
  4. Supabase valida los tokens con el proveedor y crea una sesión de usuario
  5. Supabase devuelve su propio token JWT para las peticiones autenticadas de tu app

Configuración del plugin de Google

El plugin necesita tu ID de cliente web para todas las plataformas y, opcionalmente, un ID de cliente de iOS para funciones específicas de 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'
  }
});

Puntos clave para Google:

  • Usa la ID de cliente web (no los client IDs de Android/iOS) para el webClientId campo
  • El plugin funcionará en todas las plataformas solo con el Web Client ID
  • El iOSClientId es opcional y solo se usa para funciones de Google en iOS

Configuración del plugin de Apple

La configuración de Apple varía entre iOS y Android:

Para iOS (Sign in with Apple nativo):

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

Para Android/Web (requiere Service ID). Usa las mismas reglas de redirección que buildApplePluginConfig() en el tutorial de 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,
        },
});

Puntos clave para Apple:

  • iOS usa Sign in with Apple nativo (sin configuración extra)
  • Android usa tu Service ID y la URL de apple-signin-callback Supabase Edge Function
  • Web usa tu Service ID y window.location.href, que debe coincidir con las Apple Return URLs

Configuración del plugin de Facebook

Facebook requiere tu App ID y 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
  }
});

Puntos clave para Facebook:

  • Usa el mismo App ID que configuraste en Supabase
  • El Client Token está en la configuración básica de tu App de Facebook
  • limitedLogin: true activa la función Limited Login de Facebook (solo iOS)
  • Importante: See our Guía de configuración de Facebook para info detallada de Limited Login, incluyendo ATT

Inicializa @capgo/capacitor-social-login una vez al arrancar la app de React

Completar la inicialización del plugin

Así puedes inicializar todos los providers juntos:

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

Notas importantes:

  • Llama a initialize() una vez al iniciar la app, no antes de cada login
  • Solo necesitas configurar los providers que vayas a usar
  • Las credenciales aquí son de los providers originales, no de Supabase
  • Asegúrate de que las credenciales del proveedor coincidan con lo que configuraste en Supabase

Cliente de Supabase para React y capa de auth

Instala el cliente de Supabase si aún no lo has hecho:

bun add @supabase/supabase-js

Crea un único cliente para todo el árbol de 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,
  },
});

Helpers de nonce para Google + Supabase

Supabase espera un nonce en bruto en signInWithIdToken y un digest SHA-256 enviado a Google. El Guía de Google con Supabase documenta el flujo completo. Helpers mínimos:

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

Conecta Social Login + Supabase en un módulo (patrón del ejemplo 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 por plataforma (ver Configuración general de Supabase con Apple, Android, Web):

  • iOS: buildApplePluginConfig() devuelve {}. El inicio de sesión nativo con Apple usa tu bundle ID. No redirectUrl.
  • Android: clientId es tu Apple Service ID. redirectUrl es tu Supabase Edge Function (apple-signin-callback). Despliega la función, configura el Apple Return URL en ese endpoint y añade el intent filter de deep link de la app para que el flujo pueda volver al WebView (Guía de Apple con Supabase en Android).
  • Web: clientId es tu Service ID. redirectUrl es window.location.href, que debe coincidir con un Return URL en el Apple Developer Portal (Guía de Apple con Supabase en Web).

ensureSocialLoginInitialized() añade el apple proveedor solo cuando isAppleLoginConfigured() es true, así que una configuración solo de Google no envía credenciales vacías de Android o Apple web.

El plugin devuelve result.idToken en todas las plataformas (AppleProviderResponse en @capgo/capacitor-social-login). Registra tanto el iOS App ID como el Service ID en Supabase cuando lances para múltiples plataformas.

Expón el estado de la sesión a los componentes:

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

UI de login en React y rutas protegidas

Pantalla de login de ejemplo con botones de Google y Apple en un layout móvil

Panel de login:

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

Vista de debug de la sesión (reemplaza con tu UI de cuenta real más tarde):

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

JSON de la sesión iniciada en un panel de debug de React

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

Monta la app en main.tsx como siempre. Tras un login correcto con el proveedor, onAuthStateChange actualizaciones session y React Router redirige al usuario a /account.

Opcional: Facebook

Facebook sigue el mismo signInWithIdToken patrón con el access token del plugin. Consulta configuración de Facebook y el bloque del proveedor en Paso 4.

Añade Capacitor a la app de React

Genera el bundle web y luego añade los proyectos nativos:

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 aloja el build de Vite mientras los SDK nativos gestionan el social login

Sincroniza tras cada build web:

bun run build
bunx cap sync

Abre el IDE nativo cuando estés listo para probar en dispositivos:

bunx cap open ios
bunx cap open android

Completa los pasos de Google y Apple antes de probar en hardware:

Los tutoriales que se ejecutan supabase.auth.signInWithOAuth dentro de un WebView suelen requerir Universal Links o App Links así que el SO devuelve el control a la app tras la redirección de Google. Native Google sign-in con un Token de ID evita ese bucle de redirección porque el plugin nunca abre un flujo de OAuth en el navegador. Apple en Android es distinto: sigue usando el redireccionamiento de la Edge Function y un deep link intent filter para que la WebView pueda reanudarse tras el login de Apple.

Aún puedes configurar deep links para otras funciones (emails de reset de contraseña, magic links, URLs de marketing). Añade las mismas rutas a Autenticación > Configuración de URL en Supabase y en tus apple-app-site-association / intent filters de Android al añadir esos flujos.

Paso 8: Configuración por plataforma

Configuración de iOS

Para instrucciones detalladas de iOS, consulta nuestras guías por plataforma:

Resumen rápido - Añadir a 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>

Sigue las guías enlazadas para la configuración completa de iOS, incluyendo el proyecto de Xcode.

Configuración de Android

Para instrucciones detalladas de Android, consulta nuestras guías específicas:

Configuración esencial de Android:

1. Obtén tu huella digital SHA-1 (requerido para 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. Configura AndroidManifest.xml - Añadir a 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. Añade recursos de Facebook a 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>

Sigue las guías de la plataforma para la configuración completa de Android, incluyendo Google Play Services y el package name.

Paso 9: Usar la base de datos Supabase con usuarios autenticados

Una vez autenticados los usuarios, puedes usar la base de datos de Supabase con Row Level Security (RLS):

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

Consideraciones de seguridad importantes

  1. Nunca expongas claves sensibles en el code de tu cliente
  2. Usa variables de entorno para la configuración
  3. Activa Row Level Security en Supabase
  4. Valida los tokens en tu backend si es necesario
  5. Gestiona el refresh de tokens automáticamente con Supabase

Problemas conocidos y solución de errores

Error de nonce en Google (especialmente en iOS)

Si Supabase devuelve un error de nonce, es posible que Google haya devuelto un ID token en caché. Cierra sesión en Google mediante el plugin, reintenta una vez y confirma que pasas nonceDigest a SocialLogin.login y rawNonce a signInWithIdToken. El app de ejemplo reintentos después de SocialLogin.logout.

Errores de audiencia del token

Registra cada client ID de Google (web, iOS, Android) en el proveedor de Google de Supabase. El aud claim en el ID token debe coincidir con uno de ellos.

Tutoriales de redirección OAuth vs esta guía

Posts del blog que usan signInWithOAuth en una WebView puede fallar en móviles si el redirect abre Safari en vez de tu app. Prefiere login nativo + signInWithIdToken para Capacitor, o sigue configuración web de Social Login para redirecciones de navegador.

Comprobaciones por plataforma

Discrepancia de tokens y errores de red

  • Sincroniza las credenciales entre Google Cloud, Supabase y SocialLogin.initialize
  • Maneja estados de carga y error en React (ver LoginPanel arriba)

Conclusión

Ya tienes un sistema de autenticación completo que combina el backend robusto de Supabase con capacidades de social login nativo. Esta configuración ofrece:

  • Autenticación social nativa y segura
  • Gestión de tokens sin fricciones
  • Integración de base de datos en tiempo real
  • Compatibilidad multiplataforma

La combinación de Supabase y el plugin Capgo Social Login ofrece una solución de autenticación potente y escalable para tus apps Capacitor.

Para funciones más avanzadas como autenticación multifactor o claims personalizados, consulta la documentación de Supabase y la documentación del plugin Social Login.

Continuar desde Configurar autenticación de Supabase con el plugin Social Login de Capacitor

Si estás usando Configurar autenticación de Supabase con el plugin Social Login de Capacitor para planificar los flujos de autenticación y de cuenta, conéctalo con @capgo/capacitor-social-login para los detalles de implementación en @capgo/capacitor-social-login, @capgo/capacitor-passkey para el detalle de implementación en @capgo/capacitor-passkey, @capgo/capacitor-native-biometric para el detalle de implementación en @capgo/capacitor-native-biometric, Autenticación de dos factores para el detalle de implementación en la autenticación de dos factores, y SSO (Enterprise) para el detalle de implementación en SSO (Enterprise).

Live updates para apps Capacitor

Cuando un bug de la capa web está en producción, publica el fix a través de Capgo en lugar de esperar días a la aprobación de la app store. Los usuarios reciben la actualización en segundo plano mientras los cambios nativos siguen el flujo de revisión habitual.

Lo último de nuestro blog

Capgo te da la información clave que necesitas para crear una app móvil realmente profesional.