Streamlining User Authentication: Integrating Firebase with Social Login via Google API Provider (Part 9) in Your Angular-15 Ionic-7 App

Welcome back to my blog series on building a cross-platform mobile app with Angular 15 and Ionic 7! In this ninth part, we will learn how to add Firebase authentication with social login using Google API provider. This will allow our users to sign in with their Google accounts and access the features of our app securely and conveniently.

Firebase is a powerful platform that provides various services for web and mobile development, such as hosting, database, storage, analytics, and more. One of its most popular features is authentication, which supports multiple methods of signing in, such as email/password, phone number, and social providers like Google, Facebook, Twitter, etc. In this tutorial, we will focus on integrating Google as a social provider for our app. We will use the Firebase SDK to communicate with the Firebase backend and the Google API to get the user's profile information.

By the end of this tutorial, you will have a fully functional app that can authenticate users with their Google accounts and display their profile information on the home screen. Let's get started!

Once I have set up the basic authentication via Email and password, it becomes relatively easier to use the Firebase service providers for multiple social media logins. Although there are certain configurations that need to be well in place to make them work properly. Here I will implement authentication via Google.

First off, I will go to the Firebase console and within the authentication settings, under Sign In methods, I will add Google as a provider and enable it. Since Firebase is already provided by Google, it will create the Web SDK configuration automatically as demonstrated in Figure 32:

Figure 32: Google provider enabled in firebase authentication sign in methods.


Now to make this authentication work, I had to go to the Google Cloud platform on Credentials – APIs and services – grange-mobile-karan – Google Cloud console where all the API keys are listed and OAuth 2.0 Client IDs are listed which are automatically generated via Firebase. First, I had to create another Web client ID and entered the http://localhost:8100 under Authorised Javascript origins without which the authentication doesn’t function properly. Also, in the OAuth consent screen, I had to set up the app and enter the OAuth domain of grange-mobile-karan.firebaseapp.com under the Authorised domains; and enter email and profile under the ‘Your non-sensitive scopes’ to access the user-info in my application. Also, the newly created client ID needs to be entered in the sign-in method under Google provider’s Whitelist client IDs as shown in Figure 32 to connect Firebase with the new client ID. Also, the following meta tags need to be added in the index.html file of the application:

<meta name="google-signin-scope" content="profile email">

  <meta name="google-signin-client_id" content="446380689792-<YOUR NEWLY CREATED CLIENT ID>.apps.googleusercontent.com">

This was the initial setup to make the Google API work properly.

Once this was setup, I used the Firebase documentation Authenticate Using Google with JavaScript  |  Firebase to import the necessary authentication providers in my application. I begin by importing the following modules in main.ts file as follows:

...
import {
  GoogleAuthProvider,
  getAuth,
  provideAuth,
} from '@angular/fire/auth';
...

bootstrapApplication(AppComponent, {
  providers: [
    AuthGuard,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
    importProvidersFrom(
      ...
      GoogleAuthProvider,
      ...
      provideFirebaseApp(() => initializeApp(environment.firebase)),
      provideFirestore(() => getFirestore()),
      provideStorage(() => getStorage()),
      provideAuth(() => getAuth()),
      AuthGuard
    ),
    provideRouter(routes),
  ],
});

Next, I will use my previously created Firebase authentication service and write the logic to access the Google authentication in auth.service.ts file as follows:

import {
  Auth,
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
  signInWithPopup,
  signOut,
} from '@angular/fire/auth';

import { GoogleAuthProvider } from 'firebase/auth';

@Injectable({
  providedIn: 'root',
})
export class AuthService {
 
  constructor(private auth: Auth) {} //inject the auth service

  async firebaseLoginWithGoogle() {
    const provider = new GoogleAuthProvider();
    const user = await signInWithPopup(this.auth, provider);
    // console.log(user);
    return user;
  }

  async firebaseLogoutWithGoogle() {
    const user = await signOut(this.auth);
    // console.log(user);
    return user;
  }
}

The above code defines an AuthService class with two methods firebaseLoginWithGoogle() and firebaseLogoutWithGoogle(). This is in continuation to the previous methods written for basic login and register using user email and password. The constructor of the class takes an Auth object which is an instance of the Firebase auth service, injected as a dependency. The firebaseLoginWithGoogle() method uses the GoogleAuthProvider object to authenticate a user using their Google credentials, and returns a Promise with the user object. This method uses the signInWithPopup() method of the auth object to initiate the Google sign-in process. The firebaseLogoutWithGoogle() method logs out the currently signed-in user from the app and returns a Promise with the user object. This method uses the signOut() method of the auth object to sign out the user.

Finally, I write the logic to make use of this service in the previously created login page which is login.page.ts file as follows:

...
import { AuthService } from 'src/app/services/auth.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.page.html',
  styleUrls: ['./login.page.scss'],
  standalone: true,
  imports: [IonicModule, CommonModule, FormsModule, ReactiveFormsModule],
})
export class LoginPage implements OnInit {

  googleUser: any = null; // the google user object that will be returned from the google auth plugin

  public progress = 0;

  constructor(
    private router: Router,
    private authService: AuthService,
    private toastCtrl: ToastController
  ) {}

  ngOnInit() {}

  async googleLogin() {
    const user = await this.authService.firebaseLoginWithGoogle(); // login the user with google using the firebase login with google method in the auth service
    if (user) {
      this.googleUser = user; // set the googleUser to the user returned from the firebase login with google method in the auth service
      console.log(this.googleUser); // log the googleUser to the console
      // if the user is logged in, navigate to the profile page

      // display a progress bar for 5 seconds
      setInterval(() => {
        this.progress += 0.01;
        // Reset the progress bar when it reaches 100%
        // to continuously show the demo
        if (this.progress > 1) {
          setTimeout(() => {
            this.progress = 0;
          }, 1000);
        }
      }, 50);
      setTimeout(() => {
        this.router.navigateByUrl('/tabs/tab4', { replaceUrl: true });
      }, 5000);
      //display a toast message to the user
      const toast = await this.toastCtrl.create({
        message: 'You are signed in with Google.',
        duration: 3000,
        position: 'bottom',
      });
      await toast.present();
    }
  }

  async googleSignOut() {
    // await GoogleAuth.signOut(); // sign out of google
    await this.authService.firebaseLogoutWithGoogle(); // logout of google using the firebase logout with google method in the auth service
    this.googleUser = null; // set the google user to null
    //display a toast message to the user
    const toast = await this.toastCtrl.create({
      message: 'You are signed out of Google.',
      duration: 3000,
      position: 'bottom',
    });
    await toast.present();
  }
}

In the above code, the googleLogin method is used for logging in a user with Google using Firebase authentication. Once the user is logged in, it sets the googleUser property to the user object returned from the Firebase authentication service and logs the user object to the console. It also starts a progress bar (ref: Progress Bar | Horizontal App Progress Bar for Loading Indicator (ionicframework.com)) and after 5 seconds, it navigates to a specific page and displays a toast message to the user. The googleSignOut method is used for logging out a user from Google using Firebase authentication. It sets the googleUser property to null and displays a toast message to the user.

Finally, I will add a Google Login and Logout button in the login.page.html file as follows:

<ion-header [translucent]="false">
  <ion-toolbar>
    <ion-title>Login/Sign Up</ion-title>
    <ion-progress-bar [value]="progress"></ion-progress-bar>
    <ion-buttons slot="start">
      <ion-back-button defaultHref="/"></ion-back-button>
    </ion-buttons>
    <ion-buttons slot="end">
      <ion-menu-button menu="main-menu"></ion-menu-button>
    </ion-buttons>
  </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true" class="ion-padding">
  ...

  <ion-card class="ion-padding">
    <ion-button
      class="ion-margin-top"
      (click)="googleLogin()"
      expand="full"
      fill="solid"
      shape="round"
      *ngIf="!googleUser"
    >
      <ion-icon slot="start" name="logo-google"></ion-icon>
      Google Login
    </ion-button>
    <ion-button
      (click)="googleSignOut()"
      expand="full"
      fill="outline"
      shape="round"
      *ngIf="googleUser"
    >
      Google Logout
    </ion-button>

    <ion-item lines="none" *ngIf="googleUser">
      <ion-avatar slot="start">
        <img title="user" [src]="googleUser.user.photoURL" />
      </ion-avatar>
      <ion-label>
        {{googleUser.user.displayName}}
        <p>{{googleUser.user.email}}</p>
      </ion-label>
    </ion-item>
  </ion-card>
</ion-content>

The above code is in continuation to the previous page and in here, the content includes an ion-card element with two buttons for logging in and logging out with Google.

The progress bar is bound to a class property progress using the Angular property binding syntax []. The value of the progress bar is determined by the value of the progress property, which is updated by the googleLogin method in the LoginPage class which I wrote earlier.

Using the *ngIf conditional angular directive, the login button is displayed when googleUser is null, and the logout button is displayed when googleUser is not null. These buttons are bound to the googleLogin and googleSignOut methods in the LoginPage class respectively. If the user is logged in with Google, their profile picture, display name, and email address are displayed using an ion-item element with an ion-avatar and an ion-label. This section is only displayed when googleUser is not null. Figure 33 and 34 demonstrate the working of this authentication feature.

Figure 33: Google sign in pop up window appears on web to ask for account selection.



Figure 34: Google login successful with user name and email displayed and progress bar on top.



Now, I have tried multiple ways to get this authentication working. There was a way to use the ‘@codetrix-studio/capacitor-google-auth’ capacitor plugin sourced from @codetrix-studio/capacitor-google-auth - npm (npmjs.com), which did take a lot of effort to enter the client id and token details within the application’s code directly from Google Cloud Platform, but since there is no involvement of firebase, the authentication guards set up earlier fail to work and the user doesn’t get registered in the firebase user list. So I decided to go ahead with the firebase provider since everything stays in one place in this way and the API keys, Client IDs and tokens need only be placed within the firebase console and not anywhere else.

Figure 35: Google use successfully added to all users list

Since I am using an authentication service that already provides all the various kinds of login providers, why not use the single service instead of using the social logins separately and losing track of the users logged in. In Figure 35, it is visible that the Google account I used to login into the application is successfully added to the user list alongside the previous basic email and password authentication.

Congratulations! You have successfully completed Part 9 of this series on building your first Angular-15 Ionic-7 app. In this part, you learned how to add Firebase authentication with social login using Google API provider. You also learned how to use AngularFireAuth to manage user sessions and store user data. You now have a fully functional app that allows users to sign up, sign in, and sign out using their Google account.

This is a huge achievement and you should be proud of yourself! You have mastered some of the most important skills for developing modern web and mobile applications. You have also gained valuable experience in working with Angular, Ionic, and Firebase. You are well on your way to becoming a professional developer!

But don't stop here. There is still more to learn and explore.

So stay tuned for Part 10 of this series, coming soon. And don't forget to subscribe to our blog and follow us on social media for more updates and tips on Angular, Ionic, and Firebase development. Thank you for reading and happy coding!

Popular Posts

Perform CRUD (Create, Read, Update, Delete) Operations using PHP, MySQL and MAMP : Part 4. My First Angular-15 Ionic-7 App

Visualize Your Data: Showcasing Interactive Charts for Numerical Data using Charts JS Library (Part 23) in Your Angular-15 Ionic-7 App

How to Build a Unit Converter for Your Baking Needs with HTML, CSS & Vanilla JavaScript