DEV Community

Cover image for How to implement Google OAuth2 in an Ionic/Capacitor app
Mariana Costa
Mariana Costa

Posted on • Originally published at mariana-costa.web.app

How to implement Google OAuth2 in an Ionic/Capacitor app

I've recently developed a cross-platform application with Ionic, Vue and Capacitor, and had some difficulties implementing Google OAuth2. Thus, I decided to write this article hoping that it may be useful for someone facing the same issues.
Capacitor is native runtime for building cross-platform mobile apps with JavaScript, HTML, and CSS. It provides a native mobile app that wraps a web view that hosts our web application. In the end, you have a web app running inside a mobile app, which in certain cases may have as disadvantages some performance loss.

To implement Google OAuth in a Capacitor app, there are two main steps to consider:

  • Configure your project in Google Cloud Platform
  • Implement the code needed for Google OAuth2

Configure your project in Google Cloud Platform

First, create a new project at https://console.cloud.google.com/. Then, on sidebar menu, go to API and services -> Credentials and add OAuth Client ID.
Create project at Google cloud platform

Now choose Android in the application type field. This form needs the information that was the most difficult for me to obtain: the correct SHA-1 fingerprint.
Google cloud platform form to get credentials for android

An android app can have 2 SHA-1 keys: debug and release keys. In the Google Cloud Platform Project, store the correct SHA-1 key, according to the apk you generate to test the app in an android device. I.e. if the apk was generated for build variant debug store debug SHA-1 key; if the apk was generated for release store release SHA-1 key.

Get debug SHA-1 key:

In Android Studio, open your project and click on the Gradle Bar, on the right side panel (1). Click on Tasks -> android and double-click on signingReport (2). The debug key will be displayed in your terminal (3).

How to get SHA1 for debug apk

Get release SHA-1 key:

When you generate an apk using Android Studio, you must defined a keystore and a key alias. At this time, you must define an alias for the generated certificate and where to store it. Keep it safe because it contains important information.

Create apk configuration

To get your release key, you need to use the keytool command. Go to the JDK Directory in your file system e.g. /Program Files/Java/jre-10.0.2/bin, open a terminal there and run the command keytool -list -v -keystore <path_to_the_certificate_with_keystore> -alias <alias_assigned_to_the_certificate>.

How to get SHA1 for release apk

Configure your OAuth consent screen

Add the scopes that you need for your app (e.g. email, profile), so they are presented on sign-in screen and the user can decide to grant or not your app the required permissions. Fill the other info in the form, if needed.

Create a OAuth Client ID for web application

You should also create an oAuth Client Id for web by choosing Web application in the application type field, after clicking on add OAuth Client ID.

Implement the code needed for Google OAuth2

I tested two plugins to implement Google OAuth in my app: @byteowls/capacitor-oauth2@2.1.0 and @codetrix-studio/capacitor-google-auth. Here are the implementations that I've made for both of them:

Using Capacitor OAuth2 plugin

Install the plugin yarn add @byteowls/capacitor-oauth2@2.1.0 (see docs for more details) and sync the new plugin by running npx cap sync.

<template>
  <ion-button
    expand="block"
    class="submit-button"
    @click="authenticateWithGoogle"
  >
    Authenticate with Google
  </ion-button>
</template>
<script>
import { IonButton } from '@ionic/vue'
import { OAuth2Client } from '@byteowls/capacitor-oauth2'
export default {
  components: {
    IonButton,
    IonIcon,
  },
  setup() {
    const oauth2Options = {
      authorizationBaseUrl: 'https://accounts.google.com/o/oauth2/auth',
      accessTokenEndpoint: 'https://www.googleapis.com/oauth2/v4/token',
      scope: 'email profile',
      resourceUrl: 'https://www.googleapis.com/userinfo/v2/me',
      logsEnabled: true,
      web: {
        appId: process.env.VUE_APP_OAUTH_CLIENT_ID_WEB,
        responseType: 'token',
        accessTokenEndpoint: '',
        redirectUrl: 'http://localhost:8100',
        windowOptions: 'height=600,left=0,top=0'
      },
      android: {
        appId: process.env.VUE_APP_OAUTH_CLIENT_ID_ANDROID,
        responseType: 'code',
        redirectUrl: '<your_package_name:/>'
      },
      ios: {
        appId: process.env.VUE_APP_OAUTH_CLIENT_ID,
        responseType: 'code',
        redirectUrl: '<your_package_name:/>'
      }
    }

    const authenticateWithGoogle = async () => {
      try {
        const userData = await OAuth2Client.authenticate(oauth2Options)
        const userData = {
          fullName: userResponse.name || userResponse.displayName,
          avatar: userResponse.picture,
          accessToken: userResponse.access_token,
          refreshToken: userResponse.authorization_response?.refresh_token
        }
        // add the code for the functionality your need
      } catch (error) {
        console.error(error)
      }
    }

    const logout = async () => {
      try {
        await OAuth2Client.logout()
      } catch (error) {
        console.error(error)
      }
    }

    onMounted(() => GoogleAuth.init())
    return {  authenticateWithGoogle, logout }
  },
}
</script>
Enter fullscreen mode Exit fullscreen mode

For Android, the documentation indicates to add the following configuration in AndroidManifest.xml

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="@string/custom_url_scheme" android:host="oauth" />
</intent-filter>
Enter fullscreen mode Exit fullscreen mode

While testing my the app, I was not being able to install its apk in my android device. After some trial and error attempts, I figured out that if replaced the setup described in the docs by the code below, everything worked as expected.

<intent-filter>
  <action android:name="android.intent.action.MAIN" />
  <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
Enter fullscreen mode Exit fullscreen mode

Using Capacitor Google OAuth plugin

Install the plugin yarn add @codetrix-studio/capacitor-google-auth (see docs for more details) and sync the new plugin by running npx cap sync.

<template>
<ion-button
  expand="block"
  class="submit-button"
  @click="authenticateWithGoogle"
>
  Authenticate with Google
</ion-button>
</template>
<script>
import { IonButton } from '@ionic/vue'
import { onMounted } from 'vue'
import { GoogleAuth } from '@codetrix-studio/capacitor-google-auth'
export default {
components: {
  IonButton,
  IonIcon,
},
setup() {
  const authenticateWithGoogle = async () => {
    try {
      const userResponse = await GoogleAuth.signIn()
      const userData = {
        fullName: userResponse.name || userResponse.displayName,
        avatar: userResponse.picture,
        accessToken: userResponse.access_token,
        refreshToken: userResponse.authorization_response?.refresh_token
      }
      // add the code for the functionality your need
    } catch (error) {


      console.error(error)
    }
  }

  const logout = async () => {
    try {
      await OAuth2Client.logout()
    } catch (error) {
      console.error(error)
    }
  }
    return {  authenticateWithGoogle, logout }
  },
}
</script>
Enter fullscreen mode Exit fullscreen mode

For Android app, add the following configuration to capacitor.config.json file:

{
  "plugins": {
    "GoogleAuth": {
      "scopes": ["profile", "email"],
      "serverClientId": "YOUR_WEB_OAUTH_CLIENT_ID",
      "forceCodeForRefreshToken": true
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Be aware that you must use the Web OAuth Client ID for these configurations, otherwise you'll not be able to sign-in when testing on a real android device.

For Android app, add the following configuration to strings.xml file:

<resources>
  <string name="server_client_id">YOUR_WEB_OAUTH_CLIENT_ID</string>
</resources>
Enter fullscreen mode Exit fullscreen mode

The documentation also indicates to add the following configuration to MainActivity.java file:

package <your_package_name:/>;
import android.os.Bundle;
import com.getcapacitor.BridgeActivity;
import com.getcapacitor.Plugin;
import com.codetrixstudio.capacitor.GoogleAuth.GoogleAuth;
import java.util.ArrayList;
public class MainActivity extends BridgeActivity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
      add(GoogleAuth.class);
    }});
  }
}
Enter fullscreen mode Exit fullscreen mode

However, this configuration was causing errors for the other plugins implemented in the app, and apparently they needed to be activated in the same way as capacitor-google-auth plugin in MainActivity.java file. After some experiments, I found out that Google OAuth was working without this configuration, so I removed it. Just be sure that you have the plugin registered on android\app\src\main\assets\capacitor.plugins.json file.

{
  "pkg": "@codetrix-studio/capacitor-google-auth",
  "classpath": "com.codetrixstudio.capacitor.GoogleAuth.GoogleAuth"
}
Enter fullscreen mode Exit fullscreen mode

And that's all I had to share. If you want to check the implementation of Google OAuth in the Ionic/Capacitor app I developed, you can check the code here and download the app here. Hope to "see" you in my next post 👋.

Discussion (0)