Firebase Google Login in Ionic Capacitor App — Step by Step Guide

In this article we going to learn how to implement Google Sign-In using Firebase Authentication in an Ionic Capacitor app — so users can log in with their Google account on Android, iOS, and in the browser.

Google login is one of those features users actually prefer over email/password. No form to fill, no password to remember, one tap and they're in. And from our side as developers, Firebase handles everything — token management, user creation, session persistence. We just wire up the plugin and call the sign-in method.

The tricky part is that Google Sign-In works differently depending on the platform. On Android and iOS we use the @codetrix-studio/capacitor-google-auth plugin which opens the native Google sign-in dialog. In the browser we use Firebase's signInWithPopup. We need to handle both cases in one codebase.

This tutorial shows how to:

  • Set up Google Sign-In in Firebase Console
  • Configure the Google Auth Capacitor plugin for Android and iOS
  • Set up OAuth credentials in Google Cloud Console
  • Create an AuthService that handles Google login on native and web
  • Build a login page with Google Sign-In button
  • Handle the signed-in user and store their profile data

How Google Sign-In Works in Capacitor

Before jumping into code, let's understand the flow so nothing surprises us later.

On Android and iOS (native):

  1. User taps "Sign in with Google"
  2. Native Google Sign-In dialog opens (the same one they see in other apps)
  3. User selects their Google account
  4. Plugin returns an ID token
  5. We pass that token to Firebase Auth to create a Firebase session

In the browser:

  1. User clicks "Sign in with Google"
  2. Firebase opens a popup window with Google's sign-in page
  3. User signs in on Google
  4. Firebase creates the session automatically

Same result — a Firebase user — but different mechanisms. Our code needs to detect the platform and use the right method.


Step 1 : Enable Google Sign-In in Firebase Console

Go to console.firebase.google.com → our project → Build → Authentication → Sign-in method.

Click Google in the list of providers. Toggle it to Enabled.

Add a Project support email — this shows on the Google consent screen. Use our email or a support email.

Click Save.

Firebase automatically creates an OAuth client ID for our project when we enable Google Sign-In. We'll see it used in later steps.


Step 2 : Install the Google Auth Plugin

Install the Capacitor Google Auth plugin :

npm install @codetrix-studio/capacitor-google-auth
npx cap sync

Step 3 : Get the Web Client ID from Google Cloud Console

We need the Web Client ID from Google Cloud Console — this is different from the Android or iOS client IDs.

Go to console.cloud.google.com. Select our Firebase project from the project dropdown at the top.

Go to APIs & Services → Credentials.

Under OAuth 2.0 Client IDs, we'll see several client IDs that Firebase created automatically. Look for the one with type Web application — it usually has "Web client (auto created by Google Service)" in the name.

Click on it. Copy the Client ID. It looks like this :

123456789-abcdefghijklmnopqrstuvwxyz.apps.googleusercontent.com

This is our Web Client ID — we need it in the plugin configuration.


Step 4 : Configure the Plugin

In capacitor.config.ts :

import { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  appId: 'com.yourcompany.appname',
  appName: 'Your App',
  webDir: 'www',
  plugins: {
    GoogleAuth: {
      scopes: ['profile', 'email'],
      serverClientId: 'YOUR_WEB_CLIENT_ID_HERE.apps.googleusercontent.com',
      forceCodeForRefreshToken: true
    }
  }
};

export default config;

Replace YOUR_WEB_CLIENT_ID_HERE with the actual Web Client ID we copied from Google Cloud Console.

Run sync after updating the config :

npx cap sync

Step 5 : Configure Android

For Android we need to add the google-services.json file to our Android project. This file links our Android app to Firebase.

In Firebase Console, go to Project Settings → Your apps. Find the Android app. Click Download google-services.json.

Copy the downloaded file to :

android/app/google-services.json

Now open android/app/build.gradle and make sure the Google services plugin is applied :

apply plugin: 'com.google.gms.google-services'

Open android/build.gradle and make sure the Google services classpath is in the dependencies :

dependencies {
    classpath 'com.google.gms:google-services:4.4.0'
}

Also in android/app/build.gradle, inside defaultConfig add our SHA-1 certificate fingerprint. Firebase needs this to verify our Android app for Google Sign-In.

Get the SHA-1 fingerprint using keytool. For the debug keystore :

keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android

Copy the SHA-1 value. Go to Firebase Console → Project Settings → Android app → Add fingerprint. Paste the SHA-1 and click Save.

For release builds, we need to add the SHA-1 from our release keystore too — otherwise Google Sign-In won't work on production builds.

Run npx cap sync android after all these changes.


Step 6 : Configure iOS

For iOS, download the GoogleService-Info.plist from Firebase Console → Project Settings → iOS app.

In Xcode, right-click on the App folder in the project navigator. Click Add Files to "App". Select the GoogleService-Info.plist file. Make sure Copy items if needed is checked.

Open ios/App/App/AppDelegate.swift and add the Google Sign-In URL scheme handler :

import UIKit
import Capacitor
import GoogleSignIn

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ app: UIApplication, open url: URL,
                     options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
        return GIDSignIn.sharedInstance.handle(url)
    }
}

Also add the URL scheme in Xcode. Open the Info.plist file in Xcode. Add a new item URL types. Add a URL scheme using our REVERSED_CLIENT_ID from GoogleService-Info.plist.

The REVERSED_CLIENT_ID looks like this : com.googleusercontent.apps.123456789-abcdefgh

This is the CLIENT_ID but reversed. Find it in GoogleService-Info.plist under the key REVERSED_CLIENT_ID.


Step 7 : Create the AuthService with Google Sign-In

Now the actual code. Open or update src/app/services/auth.service.ts :

import { Injectable, signal } from '@angular/core';
import {
  signInWithCredential,
  signInWithPopup,
  GoogleAuthProvider,
  signOut,
  onAuthStateChanged,
  User
} from 'firebase/auth';
import { GoogleAuth } from '@codetrix-studio/capacitor-google-auth';
import { Platform } from '@ionic/angular';
import { auth } from '../firebase.config';
import { Router } from '@angular/router';

@Injectable({ providedIn: 'root' })
export class AuthService {

  currentUser = signal<User | null>(null);
  isLoggedIn = signal<boolean>(false);

  constructor(
    private platform: Platform,
    private router: Router
  ) {
    onAuthStateChanged(auth, (user) => {
      this.currentUser.set(user);
      this.isLoggedIn.set(!!user);
    });
  }

  async signInWithGoogle(): Promise<void> {
    if (this.platform.is('capacitor')) {
      await this.signInWithGoogleNative();
    } else {
      await this.signInWithGoogleWeb();
    }
  }

  // Native sign-in (Android and iOS)
  private async signInWithGoogleNative(): Promise<void> {
    // Initialize GoogleAuth plugin
    await GoogleAuth.initialize({
      clientId: 'YOUR_WEB_CLIENT_ID_HERE.apps.googleusercontent.com',
      scopes: ['profile', 'email'],
      grantOfflineAccess: true
    });

    // Open Google sign-in dialog
    const googleUser = await GoogleAuth.signIn();

    // Get the ID token from the response
    const idToken = googleUser.authentication.idToken;

    // Create Firebase credential from the Google ID token
    const credential = GoogleAuthProvider.credential(idToken);

    // Sign in to Firebase with the credential
    const result = await signInWithCredential(auth, credential);
    this.currentUser.set(result.user);

    await this.router.navigate(['/home']);
  }

  // Web sign-in (browser)
  private async signInWithGoogleWeb(): Promise<void> {
    const provider = new GoogleAuthProvider();
    provider.addScope('profile');
    provider.addScope('email');

    const result = await signInWithPopup(auth, provider);
    this.currentUser.set(result.user);

    await this.router.navigate(['/home']);
  }

  async signOut(): Promise<void> {
    // Sign out from Firebase
    await signOut(auth);

    // Sign out from Google (native only)
    if (this.platform.is('capacitor')) {
      try {
        await GoogleAuth.signOut();
      } catch (e) {
        // Ignore if already signed out
      }
    }

    this.currentUser.set(null);
    this.isLoggedIn.set(false);
    await this.router.navigate(['/login']);
  }

  getUser(): User | null {
    return this.currentUser();
  }
}

The key part is this.platform.is('capacitor'). This returns true when running as a native Android or iOS app. False when running in the browser. We use this to decide which sign-in method to call.

For native — we use the @codetrix-studio/capacitor-google-auth plugin to get the Google ID token, then pass it to Firebase via signInWithCredential. Firebase creates a user session from the token.

For web — we use Firebase's own signInWithPopup which handles everything in one call.


Step 8 : Build the Login Page

Update our login page to add the Google Sign-In button :

import { Component } from '@angular/core';
import { IonicModule, LoadingController, ToastController } from '@ionic/angular';
import { CommonModule } from '@angular/common';
import { AuthService } from '../../services/auth.service';

@Component({
  selector: 'app-login',
  standalone: true,
  imports: [IonicModule, CommonModule],
  template: `
    <ion-header>
      <ion-toolbar color="primary">
        <ion-title>Login</ion-title>
      </ion-toolbar>
    </ion-header>

    <ion-content class="ion-padding">
      <div style="max-width: 400px; margin: 60px auto; text-align: center;">

        <ion-icon name="person-circle-outline"
          style="font-size: 80px; color: var(--ion-color-primary); margin-bottom: 20px;">
        </ion-icon>

        <h2>Welcome</h2>
        <p style="color: grey; margin-bottom: 40px;">Sign in to continue</p>

        <!-- Google Sign-In Button -->
        <ion-button
          expand="block"
          color="light"
          (click)="signInWithGoogle()"
          [disabled]="loading"
          style="margin-bottom: 16px; --border-radius: 8px;">
          <ion-icon name="logo-google" slot="start" color="danger"></ion-icon>
          {{ loading ? 'Signing in...' : 'Continue with Google' }}
        </ion-button>

        <ion-text color="danger" *ngIf="errorMessage">
          <p style="margin-top: 16px;">{{ errorMessage }}</p>
        </ion-text>

      </div>
    </ion-content>
  `
})
export class LoginPage {
  loading = false;
  errorMessage = '';

  constructor(
    private authService: AuthService,
    private loadingController: LoadingController,
    private toastController: ToastController
  ) {}

  async signInWithGoogle() {
    this.loading = true;
    this.errorMessage = '';

    const loader = await this.loadingController.create({
      message: 'Signing in with Google...',
      duration: 30000
    });
    await loader.present();

    try {
      await this.authService.signInWithGoogle();
    } catch (error: any) {
      this.errorMessage = this.getErrorMessage(error.code || error.message);
      await this.showErrorToast(this.errorMessage);
    } finally {
      this.loading = false;
      await loader.dismiss();
    }
  }

  private getErrorMessage(code: string): string {
    if (code === 'auth/popup-closed-by-user' || code?.includes('cancelled')) {
      return 'Sign-in was cancelled.';
    }
    if (code === 'auth/network-request-failed') {
      return 'No internet connection. Please try again.';
    }
    if (code?.includes('SIGN_IN_CANCELLED') || code?.includes('canceled')) {
      return 'Google sign-in was cancelled.';
    }
    return 'Sign-in failed. Please try again.';
  }

  private async showErrorToast(message: string) {
    const toast = await this.toastController.create({
      message,
      duration: 3000,
      color: 'danger',
      position: 'bottom'
    });
    await toast.present();
  }
}

Step 9 : Show User Profile After Login

In the home page, we can display the Google profile info Firebase gives us. Firebase Auth stores the user's display name, email, and photo URL from their Google account :

import { Component } from '@angular/core';
import { IonicModule } from '@ionic/angular';
import { CommonModule } from '@angular/common';
import { AuthService } from '../services/auth.service';

@Component({
  selector: 'app-home',
  standalone: true,
  imports: [IonicModule, CommonModule],
  template: `
    <ion-header>
      <ion-toolbar color="primary">
        <ion-title>Home</ion-title>
        <ion-buttons slot="end">
          <ion-button (click)="signOut()">
            <ion-icon name="log-out-outline"></ion-icon>
          </ion-button>
        </ion-buttons>
      </ion-toolbar>
    </ion-header>

    <ion-content class="ion-padding">
      <div style="text-align: center; margin-top: 40px;">

        <!-- User profile photo from Google -->
        <img
          *ngIf="user?.photoURL"
          [src]="user?.photoURL"
          style="width: 80px; height: 80px; border-radius: 50%; margin-bottom: 16px;"
          referrerpolicy="no-referrer" />

        <ion-avatar *ngIf="!user?.photoURL" style="margin: 0 auto 16px;">
          <ion-icon name="person-circle" style="font-size: 80px;"></ion-icon>
        </ion-avatar>

        <h2>{{ user?.displayName || 'Welcome' }}</h2>
        <p style="color: grey;">{{ user?.email }}</p>

        <ion-chip color="success" style="margin-top: 8px;">
          <ion-icon name="checkmark-circle-outline"></ion-icon>
          <ion-label>Signed in with Google</ion-label>
        </ion-chip>

      </div>
    </ion-content>
  `
})
export class HomePage {
  get user() {
    return this.authService.currentUser();
  }

  constructor(public authService: AuthService) {}

  async signOut() {
    await this.authService.signOut();
  }
}

user?.photoURL is the profile picture from their Google account. user?.displayName is their full name. user?.email is their Gmail address. Firebase automatically populates all of these when the user signs in with Google.

Note the referrerpolicy="no-referrer" on the image tag — Google profile photos require this attribute to load correctly in Ionic/Capacitor apps.


Common Issues

"Sign in failed: 12500" on Android

This error means Google Sign-In couldn't verify our app. Most likely the SHA-1 fingerprint isn't added in Firebase Console. Add both debug and release SHA-1 fingerprints and download the updated google-services.json.

"DEVELOPER_ERROR" on Android

Same root cause — SHA-1 mismatch. Also check that the google-services.json in android/app/ is the latest download from Firebase Console. Old google-services.json from before we added the SHA-1 fingerprint won't work.

Google Sign-In popup blocked in browser

Browsers block popups that aren't triggered directly by user interaction. Make sure signInWithPopup is called inside the button click handler — not inside a Promise or setTimeout. In our code it's called directly from the button click method, which is correct.

Sign in works on debug but not release APK

The release keystore SHA-1 isn't added to Firebase Console. Generate the SHA-1 from our release keystore with keytool -list -v -keystore my-release-key.jks and add it in Firebase Console → Project Settings → Android app → Add fingerprint.

"GoogleAuth.initialize is not a function" in browser

The @codetrix-studio/capacitor-google-auth plugin doesn't work in the browser. Our AuthService correctly checks platform.is('capacitor') before calling it. In browser mode, signInWithGoogleWeb() uses Firebase's popup method instead.

Profile photo not loading

Add referrerpolicy="no-referrer" to the img tag. Google's photo CDN requires this header otherwise the request is blocked.


Summary

We learned how to implement Google Sign-In with Firebase in an Ionic Capacitor app. We covered :

  • Enabling Google Sign-In provider in Firebase Console
  • Installing @codetrix-studio/capacitor-google-auth plugin
  • Getting the Web Client ID from Google Cloud Console
  • Configuring the plugin in capacitor.config.ts
  • Adding google-services.json and SHA-1 fingerprint for Android
  • Adding GoogleService-Info.plist and URL scheme for iOS
  • Building AuthService that detects the platform and uses native sign-in on Capacitor and popup on web
  • Converting the Google ID token to a Firebase credential with signInWithCredential
  • Login page with Google Sign-In button, loading overlay, and error toast
  • Displaying user profile photo, name, and email from the Firebase user object
  • Fixing common errors — SHA-1 mismatch, popup blocked, release APK issues, and profile photo loading

Google Sign-In is one of the best user experience improvements we can add to an Ionic app. Once the initial setup is done — the SHA-1 fingerprints, the plist file, the URL scheme — the actual sign-in flow is just one method call. Users love it and it reduces signup friction dramatically.

I hope you like this article...

Happy coding! 🚀

Post a Comment

0 Comments