Saltar al contenido principal
Tutorial Android Capacitor

Cómo iniciar sesión con Google usando Capacitor (2026)

Configura Google Sign-In en una app de Capacitor 8: client IDs, SHA-1, URL scheme de iOS, Credential Manager de Android, verificación de ID tokens y soluciones para el error 28444.

Selector de cuenta de Google Sign-In en una app Capacitor usando el plugin Social Login de Capgo

Para añadir Google Sign-In a una app Capacitor, crea un client ID de OAuth para Web, uno para iOS y uno o más para Android en Google Cloud, instala @capgo/capacitor-social-login, llama a SocialLogin.initialize({ google: { webClientId, iOSClientId } }), luego SocialLogin.login({ provider: 'google' }). Android usa el Credential Manager de Google, iOS usa el SDK de Google Sign-In, y la web usa Google Identity Services. Los tres devuelven un ID token que debes verificar en tu servidor.

Esta guía detalla cada paso para Capacitor 8 en octubre de 2026, incluyendo las partes que suelen fallar: fingerprints SHA-1, la clave de Play App Signing y el URL scheme de iOS.

Cómo funciona Google Sign-In en una app Capacitor

Plataforma API nativo usado por el plugin Client ID pasado al plugin Otra configuración en la consola
Android Credential Manager (androidx.credentials) Web client ID como webClientId Cliente Android con package name y SHA-1
iOS Google Sign-In SDK client ID de iOS como iOSClientId URL scheme de client ID invertido en Info.plist
Web Google Identity Services Web client ID como webClientId Orígenes de JavaScript autorizados

Google bloquea OAuth dentro de WebViews embebidas con el disallowed_useragent error, por lo que cargar la página de inicio de sesión de Google en tu WebView de Capacitor no funciona. El plugin utiliza el selector de cuentas nativo.

Paso 1: Configurar Google Cloud

Crea un proyecto y la plataforma de autenticación de Google

  1. Abrir Consola de Google Cloud y crea un proyecto, o elige uno existente. Todos los client IDs deben estar en el mismo proyecto.
  2. Abrir Plataforma de Google Auth (la pantalla anteriormente llamada “OAuth consent screen”).
  3. En Branding, establece el nombre de la app que verán los usuarios, un email de soporte, tus dominios y la URL de la política de privacidad.
  4. En Audiencia, elige Externo para apps de consumo. Mientras la app esté en Pruebas, solo las cuentas listadas en Usuarios de prueba pueden iniciar sesión.
  5. En Acceso a datos, mantén el valor predeterminado openid, email y profile scopes por defecto a menos que necesites más.

No necesitas publicar en producción ni pasar la verificación para los scopes básicos. Los scopes sensibles (Calendar, Drive, Gmail) requieren verificación antes del lanzamiento público.

Crear los IDs de cliente

Ve a Plataforma de autenticación de Google > Clientes (o APIs y servicios > Credenciales) y crear:

Tipo de cliente Qué introducir Dónde va el ID
Aplicación web Orígenes de JavaScript autorizados para tu build web (por ejemplo, https://app.example.com, http://localhost:5173) webClientId
iOS Tu bundle ID, además del App Store ID y del Team ID cuando los tengas iOSClientId
Android (debug) Package name más el SHA-1 de debug Solo consola
Android (versión final) Package name más el SHA-1 de la upload key Solo consola
Android (Play Store) Package name más el SHA-1 de Play App Signing Solo consola

Obtén los valores SHA-1:

# Debug key and any signing config in build.gradle
cd android && ./gradlew signingReport

# From a signed APK you actually install
keytool -printcert -jarfile android/app/build/outputs/apk/release/app-release.apk

Para builds de Play Store, copia el SHA-1 desde Play Console > Test and release > App integrity > App signing key certificate. Si primero necesitas un keystore de release, el Generador de keystore para Android crea uno en el navegador. Nuestra guía de Google client ID profundiza en las pantallas de la consola.

Paso 2: Instalar el plugin

bun add @capgo/capacitor-social-login
bunx cap sync

Desactiva los proveedores que no uses para que sus SDKs no queden en el binario:

// capacitor.config.ts
import type { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  appId: 'com.example.app',
  appName: 'Example',
  webDir: 'dist',
  plugins: {
    SocialLogin: {
      providers: {
        google: true,
        apple: true,
        facebook: false,
        twitter: false,
      },
    },
  },
};

export default config;

Ejecuta bunx cap sync después de cambiar de proveedores.

Paso 3: Configuración de iOS

Añade el URL scheme del client ID invertido

Abre el cliente de iOS en Google Cloud y copia el URL scheme de iOS, que se ve así: com.googleusercontent.apps.1234567890-abcdef. Añádelo a ios/App/App/Info.plist antes de cerrar el </dict>:

<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>com.googleusercontent.apps.1234567890-abcdef</string>
    </array>
  </dict>
</array>

Si ya tienes un CFBundleURLTypes array para deep links, añade una nueva <dict> entrada en él en lugar de crear una segunda clave.

Deja que el SDK de Google gestione la URL de callback

En ios/App/App/AppDelegate.swift, importa SDK y enruta la URL hacia él antes de Capacitor:

import GoogleSignIn // add at the top of the file

// Replace the generated application(_:open:options:) method
func application(_ app: UIApplication, open url: URL,
                 options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
    if GIDSignIn.sharedInstance.handle(url) {
        return true
    }
    return ApplicationDelegateProxy.shared.application(app, open: url, options: options)
}

Mantén el ApplicationDelegateProxy llama a @capacitor/app sigue recibiendo tus otros deep links.

Paso 4: Configuración de Android

El inicio de sesión básico con los scopes predeterminados funciona sin cambios nativos. Si solicitas scopes adicionales o usas modo offline, el plugin necesita recibir resultados de actividad, por lo que MainActivity debe implementar la interfaz de marcador del plugin:

package com.example.app;

import android.content.Intent;
import com.getcapacitor.BridgeActivity;
import com.getcapacitor.Plugin;
import com.getcapacitor.PluginHandle;
import ee.forgr.capacitor.social.login.GoogleProvider;
import ee.forgr.capacitor.social.login.ModifiedMainActivityForSocialLoginPlugin;
import ee.forgr.capacitor.social.login.SocialLoginPlugin;

public class MainActivity extends BridgeActivity implements ModifiedMainActivityForSocialLoginPlugin {

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode >= GoogleProvider.REQUEST_AUTHORIZE_GOOGLE_MIN
                && requestCode < GoogleProvider.REQUEST_AUTHORIZE_GOOGLE_MAX) {
            PluginHandle handle = getBridge().getPlugin("SocialLogin");
            if (handle == null) return;
            Plugin plugin = handle.getInstance();
            if (plugin instanceof SocialLoginPlugin) {
                ((SocialLoginPlugin) plugin).handleGoogleLoginIntent(requestCode, data);
            }
        }
    }

    @Override
    public void IHaveModifiedTheMainActivityForTheUseWithSocialLoginPlugin() {}
}

Sin esto, las llamadas con scopes darán error: “You CANNOT use scopes without modifying the main activity”.

Para el emulador, usa una imagen de sistema con la Google Play etiqueta e inicia sesión en una cuenta de Google en los ajustes del dispositivo. Las imágenes sin Play services devuelven NoCredentialException.

Paso 5: Configuración web

Añade cada origen desde el que sirvas el web build a la lista del cliente web Orígenes de JavaScript autorizados, incluyendo el puerto (http://localhost:5173). Llama initialize temprano: el plugin inyecta el script tag de Google y el login falla si se ejecuta antes de que el script esté listo.

Paso 6: Inicializar e iniciar sesión

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

const WEB_CLIENT_ID = '1234567890-web.apps.googleusercontent.com';
const IOS_CLIENT_ID = '1234567890-ios.apps.googleusercontent.com';

export async function initAuth() {
  await SocialLogin.initialize({
    google: {
      webClientId: WEB_CLIENT_ID, // Android + web
      iOSClientId: IOS_CLIENT_ID, // iOS
      iOSServerClientId: WEB_CLIENT_ID, // same as webClientId, required for offline mode on iOS
      mode: 'online',
    },
  });
}

export async function signInWithGoogle() {
  try {
    const { result } = await SocialLogin.login({
      provider: 'google',
      options: {},
    });

    if (result.responseType !== 'online' || !result.idToken) {
      throw new Error('Expected an ID token from Google');
    }

    const res = await fetch('https://api.example.com/auth/google', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ idToken: result.idToken }),
    });
    return res.json();
  } catch (error: any) {
    if (error?.code === 'USER_CANCELLED') return null;
    throw error;
  }
}

La respuesta en línea contiene:

Campo Notas
idToken JWT de OpenID Connect. Envíalo a tu servidor
accessToken Para llamar a las APIs de Google desde el cliente. Puede ser null en Android cuando solo se solicitan alcances predeterminados
profile email, name, givenName, familyName, imageUrl, id
responseType 'online'

Opciones de visualización solo para Android

El options el objeto acepta style: 'bottom' para la interfaz de hoja inferior, además de filterByAuthorizedAccounts y autoSelectEnabled para usuarios recurrentes. Deja filterByAuthorizedAccounts desactivado si admites cuentas de Family Link. forceRefreshToken: true solicita a Android un nuevo access token en lugar de uno en caché.

Solicitar scopes adicionales

const { result } = await SocialLogin.login({
  provider: 'google',
  options: {
    scopes: ['https://www.googleapis.com/auth/calendar.readonly'],
  },
});

Recuerda el MainActivity cambio en Android y añade el scope bajo Acceso a datos en Google Cloud.

Modo online vs offline

Online (predeterminado) Offline
Devuelve ID token, access token, perfil serverAuthCode solo
Backend necesario Solo para verificar el token Sí, para intercambiar el code
refresh token de Google Se queda con Google SDK en el dispositivo Se almacena en tu servidor
Cuándo usar Solo necesitas saber quién es el usuario Tu servidor llama a las APIs de Google mientras el usuario no está
logout, isLoggedIn, refresh Soportado No soportado

El modo offline en iOS requiere iOSServerClientId, y en Android requiere el MainActivity cambio.

Cierre de sesión y comprobaciones de sesión

await SocialLogin.isLoggedIn({ provider: 'google' }); // { isLoggedIn: boolean }
await SocialLogin.logout({ provider: 'google' });

En Android, logout también limpia el estado de Credential Manager, para que el selector de cuentas aparezca de nuevo la próxima vez.

Paso 7: Verificar el token de ID en tu servidor

import { OAuth2Client } from 'google-auth-library';

const client = new OAuth2Client();

export async function verifyGoogleToken(idToken: string) {
  const ticket = await client.verifyIdToken({
    idToken,
    audience: [
      '1234567890-web.apps.googleusercontent.com',
      '1234567890-ios.apps.googleusercontent.com',
    ],
  });
  const payload = ticket.getPayload();
  if (!payload) throw new Error('Empty token payload');

  return {
    googleUserId: payload.sub,
    email: payload.email,
    emailVerified: payload.email_verified === true,
    name: payload.name,
  };
}

Usa sub como clave de usuario estable. Solo vincula una cuenta existente por correo electrónico cuando email_verified es true. Aceptar ambos client IDs como audiencia mantiene válidos los tokens de todas las plataformas. Luego emite tu propia sesión. Si usas un backend gestionado, sigue Supabase con Capacitor Social Login o el Guía de Google con Firebase. Neon Auth gestiona Google mediante una redirección OAuth, que @capgo/capacitor-neon se ejecuta nativamente.

Solución de problemas

Error Causa Solución
[28444] Developer console is not set up correctly Nombre del paquete, SHA-1 o webClientId no coincide Usa el ID de cliente Web, registra el SHA-1 del build instalado y mantén todos los clientes en un solo proyecto
Funciona en debug, falla desde Play Store Play re-firma la app Añade un cliente Android con el SHA-1 de Play App Signing
[16] Account reauth failed Cached account state is stale, account not a test user, or user disabled the app El plugin reintenta una vez automáticamente. Revisa usuarios de prueba, audiencia externa y SHA-1 de firma de Play
NoCredentialException Sin cuenta de Google en el dispositivo, o emulador sin servicios de Play Usa una imagen de sistema de Google Play e inicia sesión
USER_CANCELLED justo después de elegir una cuenta Normalmente sigue siendo un desajuste de SHA-1 o ID de cliente Corrige la consola antes de tratarlo como un cancelamiento real
Crash en iOS: “falta soporte para los siguientes URL schemes” Falta el ID de cliente inverso en Info.plist Añade la com.googleusercontent.apps... scheme
Web: “El origen indicado no está permitido para el ID de cliente indicado” Falta el origen en el cliente Web Añade el origen exacto, incluido el puerto
access_denied con “la app no ha completado el proceso de verificación de Google” La cuenta no es un usuario de prueba mientras está en Testing Añádela en Audience > Test users
Google login screen interrupted on iOS @capacitor/privacy-screen cubre la vista de SDK Llama a PrivacyScreen.disable() antes login

En Android, filtra Logcat por GoogleProvider. El plugin registra el nombre del paquete, la firma SHA-1 y un valor enmascarado webClientId, que puedes comparar con la consola en un minuto.

Publicar y mantener

Los cambios en la consola pueden tardar unas horas en propagarse, así que no rotes los client IDs el día del lanzamiento. Una vez que la configuración nativa esté en un build de la tienda, los cambios del lado del cliente, como scopes, manejo de errores o la URL del backend, pueden salir a través de actualizaciones Live Update de Capgo. Si tu equipo no tiene un Mac para releases de iOS, Build de Capgo compila y firma el binario de iOS en la nube.

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.