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
- Abrir Consola de Google Cloud y crea un proyecto, o elige uno existente. Todos los client IDs deben estar en el mismo proyecto.
- Abrir Plataforma de Google Auth (la pantalla anteriormente llamada “OAuth consent screen”).
- 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.
- 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.
- En Acceso a datos, mantén el valor predeterminado
openid,emailyprofilescopes 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.
Guías relacionadas
- Cómo iniciar sesión con Apple usando Capacitor, que necesitarás en iOS si Google es tu método de inicio de sesión principal.
- Cómo añadir autenticación a una app Capacitor para elegir entre social login, OIDC, passkeys y Better Auth.
- Página del plugin Social Login y la Docs de configuración de Google Android.