Um Google Sign-In in einer Capacitor App hinzuzufügen, erstelle Web-, iOS- und eine oder mehrere Android OAuth Client IDs in der Google Cloud, installiere @capgo/capacitor-social-login, rufe SocialLogin.initialize({ google: { webClientId, iOSClientId } }), dann SocialLogin.login({ provider: 'google' }). Android nutzt Googles Credential Manager, iOS nutzt das Google Sign-In SDK, und das Web nutzt Google Identity Services. Alle drei liefern ein ID-Token, das du auf deinem Server verifizierst.
Dieser Guide führt dich durch jeden Schritt für Capacitor 8 im Oktober 2026, inklusive der Teile, die meistens Probleme machen: SHA-1 Fingerprints, den Play App Signing Key und das iOS URL Scheme.
So funktioniert Google Sign-In in einer Capacitor-App
| Plattform | Native API, die vom Plugin genutzt werden | An das Plugin übergebene Client ID | Weitere Console-Konfiguration |
|---|---|---|---|
| Android | Credential Manager (androidx.credentials) |
Web-Client-ID als webClientId |
Android-Client mit Package-Name und SHA-1 |
| iOS | Google Sign-In mit SDK | iOS-Client-ID als iOSClientId |
Reversed Client ID URL Scheme in Info.plist |
| Web | Google Identity Services | Web-Client-ID als webClientId |
autorisierten JavaScript-Origins |
Google blockiert OAuth in eingebetteten WebViews mit disallowed_useragent Fehler, weshalb das Laden der Google-Login-Seite in deiner Capacitor WebView nicht funktioniert. Das Plugin nutzt stattdessen den nativen Account Picker.
Schritt 1: Google Cloud konfigurieren
Ein Projekt und die Google Auth Platform erstellen
- Öffne Google Cloud Console und erstelle ein Projekt oder wähle ein bestehendes aus. Alle Client-IDs müssen im selben Projekt liegen.
- Öffne Google Auth Plattform (der Bildschirm, der früher „OAuth-Zustimmungsbildschirm“ hieß).
- Unter Branding, lege den App-Namen fest, den Nutzer sehen, eine Support-E-Mail sowie deine Domains und die URL der Datenschutzerklärung.
- Unter Zielgruppe, wähle Extern für Consumer-Apps. Während die App in Testen, only the accounts listed under Testnutzer aufgelisteten Konten sich anmelden.
- Unter Datenzugriff, behalte den Standard
openid,emailundprofileScopes, außer du benötigst mehr.
Für die Basis-Scopes musst du nichts veröffentlichen oder verifizieren lassen. Sensitive Scopes (Calendar, Drive, Gmail) erfordern eine Verifizierung vor dem öffentlichen Release.
Client-IDs erstellen
Gehe zu Google Auth Platform > Clients (oder APIs & Services > Anmeldedaten) und erstelle:
| Client-Typ | Was einzugeben ist | Wo die ID platziert wird |
|---|---|---|
| Webanwendung | Autorisierte JavaScript-Origins für deinen Web-Build (z. B. https://app.example.com, http://localhost:5173) |
webClientId |
| iOS | Deine Bundle ID sowie App Store ID und Team ID, sobald verfügbar | iOSClientId |
| Android (Debug) | Package Name plus Debug SHA-1 | Nur für die Console |
| Android (Release) | Package Name plus Upload Key SHA-1 | Nur für die Console |
| Android (Play Store) | Package Name plus Play App Signing SHA-1 | Nur Konsole |
SHA-1-Werte abrufen:
# 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
Für Play Store Builds kopiere das SHA-1 aus Play Console > Test und Veröffentlichung > App-Integrität > Zertifikat des App-Signaturschlüssels. Falls du zuerst ein Release-Keystore benötigst, erstellt Android Keystore Generator eines im Browser. Unser Google Client ID Guide geht detaillierter auf die Console-Screens ein.
Schritt 2: Plugin installieren
bun add @capgo/capacitor-social-login
bunx cap sync
Deaktiviere ungenutzte Provider, damit deren SDKs nicht in der Binary landen:
// 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;
Ausführen bunx cap sync nach dem Wechsel der Provider.
Schritt 3: iOS-Konfiguration
Füge das umgekehrte Client-ID-URL-Schema hinzu
Öffne den iOS-Client in Google Cloud und kopiere das iOS-URL-Scheme, das so aussieht com.googleusercontent.apps.1234567890-abcdef. Ergänze es in ios/App/App/Info.plist vor dem schließenden </dict>:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>com.googleusercontent.apps.1234567890-abcdef</string>
</array>
</dict>
</array>
Falls du bereits ein CFBundleURLTypes Array für Deep Links hast, füge einen neuen <dict> Eintrag hinzu, anstatt einen zweiten Key zu erstellen.
Lass Google SDK die Callback-URL verarbeiten
Unter ios/App/App/AppDelegate.swift, importiere SDK und leite die URL dorthin weiter, bevor 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)
}
Behalte das ApplicationDelegateProxy ruft so @capacitor/app erhält weiterhin deine anderen Deep Links.
Schritt 4: Android-Konfiguration
Das einfache Sign-in mit Standard-Scopes funktioniert ohne native Änderungen. Wenn du zusätzliche Scopes oder nutze den Offline-Modusnutzt, muss das Plugin Activity-Results empfangen, daher MainActivity musst du das Marker-Interface des Plugins implementieren:
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() {}
}
Ohne dies schlagen Aufrufe mit scopes „You CANNOT use scopes without modifying the main activity“ fehl.
Verwenden Sie für den Emulator ein System-Image mit dem Google Play Store Melde dich in den Geräteeinstellungen bei einem Google-Konto an. Geräte ohne Play Services geben NoCredentialException.
Schritt 5: Web-Konfiguration
Füge alle Origins hinzu, von denen aus du den Web-Build bereitstellst, in die autorisierten JavaScript-Originsdes Web-Clients ein, inklusive des Ports (http://localhost:5173). Rufe initialize frühzeitig auf: Das Plugin injiziert Googles Script-Tag, und der Login schlägt fehl, wenn es läuft, bevor das Script bereit ist.
Schritt 6: Initialisieren und anmelden
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;
}
}
Die Online-Antwort enthält:
| Feld | Notizen |
|---|---|
idToken |
OpenID Connect JWT. Sende dies an deinen Server |
accessToken |
Um Google APIs vom Client aus aufzurufen. Kann null auf Android, wenn nur Standard-Scopes angefordert werden |
profile |
email, name, givenName, familyName, imageUrl, id |
responseType |
'online' |
Android-spezifische Anzeigeoptionen
Der options Objekt akzeptiert style: 'bottom' für die Bottom-Sheet-UI, plus filterByAuthorizedAccounts und autoSelectEnabled für wiederkehrende Nutzer. Lass filterByAuthorizedAccounts aus, falls du Family Link-Konten unterstützt. forceRefreshToken: true fragt Android nach einem neuen Access Token statt eines gecachten.
Zusätzliche Scopes anfordern
const { result } = await SocialLogin.login({
provider: 'google',
options: {
scopes: ['https://www.googleapis.com/auth/calendar.readonly'],
},
});
Denk an die MainActivity Änderung unter Android und füge den Scope in Datenzugriff in Google Cloud hinzu.
Online- vs. Offline-Modus
| Online (Standard) | Offline | |
|---|---|---|
| Rückgabewert | ID Token, Access Token, Profil | serverAuthCode nur |
| Backend erforderlich | Nur zur Token-Verifizierung | Ja, um den code einzutauschen |
| Google Refresh Token | Bleibt mit Google SDK auf dem Gerät | Wird auf deinem Server gespeichert |
| Anwendungsfall | Du musst nur wissen, wer der User ist | Dein Server ruft Google APIs auf, wenn der User offline ist |
logout, isLoggedIn, refresh |
Unterstützt | Nicht unterstützt |
Der Offline-Modus unter iOS benötigt iOSServerClientId, und unter Android ist die MainActivity change.
Logout und Session-Checks
await SocialLogin.isLoggedIn({ provider: 'google' }); // { isLoggedIn: boolean }
await SocialLogin.logout({ provider: 'google' });
Unter Android, logout löscht auch den Zustand des Credential Managers, sodass beim nächsten Mal der Account-Picker wieder erscheint.
Schritt 7: ID-Token auf deinem Server verifizieren
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,
};
}
Nutzt sub als stabilen User-Key. Verknüpfe ein bestehendes Konto per E-Mail nur dann, email_verified ist true. Wenn du beide Client-IDs als Audience akzeptierst, bleiben Tokens von jeder Plattform gültig. Erstelle anschließend deine eigene Session. Wenn du ein Managed Backend nutzt, folge dem Supabase mit Capacitor Social Login oder den Firebase Google Guide. Neon Auth verwaltet Google über einen OAuth-Redirect, der @capgo/capacitor-neon nativ läuft.
Fehlerbehebung
| Fehler | Ursache | Lösung |
|---|---|---|
[28444] Developer console is not set up correctly |
Package-Name, SHA-1 oder webClientId Mismatch |
Verwende die Web-Client-ID, registriere die SHA-1 des installierten Builds und führe alle Clients in einem Projekt zusammen |
| Funktioniert im Debug-Modus, schlägt im Play Store fehl | Play re-signet die App | Android-Client mit dem Play App Signing SHA-1 hinzufügen |
[16] Account reauth failed |
Der zwischengespeicherte Kontostatus ist veraltet, das Konto ist kein Testnutzer oder der Nutzer hat die App deaktiviert | Plugin führt einen automatischen Retry durch. Testnutzer, External Audience und Play Signing SHA-1 prüfen |
NoCredentialException |
Kein Google-Account auf dem Gerät oder Emulator ohne Play Services | Google Play System Image nutzen und anmelden |
USER_CANCELLED direkt nach der Account-Auswahl |
Meistens ein SHA-1 oder Client-ID Mismatch | Console-Setup fixen, bevor es als echter Abbruch gewertet wird |
| iOS Crash: „missing support for the following URL schemes“ | Reversed Client ID fehlt in Info.plist |
Füge den com.googleusercontent.apps... scheme |
| Web: „The given origin is not allowed for the given client ID“ | Origin beim Web-Client fehlt | Die exakte Origin inklusive Port hinzufügen |
access_denied mit „app has not completed the Google verification process“ |
Account ist kein Test-User im Testing-Modus | Unter Audience > Test users hinzufügen |
| Google-Login-Screen wird unter iOS unterbrochen | @capacitor/privacy-screen überdeckt die SDK View |
Rufe PrivacyScreen.disable() bevor login |
Auf Android Logcat filtern nach GoogleProvider. Das Plugin loggt den Package-Namen, die Signing-SHA-1 und einen maskierten webClientId, den du gleich mit der Console vergleichen kannst.
Deployment und Wartung
Änderungen in der Console können einige Stunden dauern, um zu propagieren; rotiere Client-IDs also nicht am Release-Tag. Sobald das Native Setup in einem Store-Build enthalten ist, können clientseitige Änderungen wie Scopes, Error Handling oder die Backend-URL über Capgo Live Updates. Wenn dein Team keinen Mac für iOS-Releases hat, Capgo Build erstellt und signiert die iOS-Binary in der Cloud.
Verwandte Guides
- So meldest du dich mit Apple über Capacitor an, was du unter iOS benötigst, wenn Google dein primärer Login ist.
- So fügen Sie einer Capacitor-App Authentifizierung hinzu um zwischen Social Login, OIDC, Passkeys und Better Auth zu wählen.
- Social Login Plugin-Seite und Google Android Setup-Docs.