← All articles

Choosing How to Run Firebase Authentication OAuth on Capacitor

Compare Capacitor plugins for Sign in with Apple, Facebook Login, and Google Auth, and wire native OAuth tokens into Firebase Authentication.

Published
Choosing How to Run Firebase Authentication OAuth on Capacitor cover image

The following article explains how to use OAuth on Capacitor:

https://zenn.dev/ubie/articles/firebase-auth-hack

Capacitor embeds a standalone WebView, so trying OAuth the way that article describes causes problems like these:

- Authentication providers such as Google block access from WebViews.
- The callback from the authentication provider opens in the device's default browser, so the user cannot return to the native app.

One way to solve that is to insist on authenticating inside the WebView, but if you combine Capacitor plugins you can implement flows like "use the provider app when it is installed (for example the Facebook app for Facebook Login), otherwise authenticate in the WebView."

Sign in With Apple

https://github.com/capacitor-community/apple-sign-in lets you use Sign in with Apple on the web and on iOS. Here is how to combine it with Firebase Authentication.

You can do it like this:

// 1. Sign in with Apple and obtain the login token
const appleLogin: SignInWithAppleResponse = await SignInWithApple.authorize().catch(() => undefined);

if (appleLogin === undefined) {
  throw 'Login failed';
}

// 2. Set the token on Firebase Authentication's OAuthProvider in a format Firebase can use
const provider = new OAuthProvider('apple.com');
const credential = provider.credential({
  idToken: appleLogin.response.identityToken,
});

if (type === 'new') {
  // 3. Create a user with OAuthProvider
  const currentUser = await signInWithCredential(this.afAuth, credential)
} else {
  // (or add the login to an existing user)
  const currentUser = await linkWithCredential(this.afAuth.currentUser, credential)
}

The key is passing the OAuth token into Firebase Authentication's OAuthProvider. That lets you implement the same flow as a WebView redirect.

Facebook Login

Use https://github.com/capacitor-community/facebook-login.

// 1. Sign in with Facebook and obtain the login token
const FACEBOOK_PERMISSIONS = ['email', 'public_profile'];
const event = await FacebookLogin.login({
  permissions: FACEBOOK_PERMISSIONS,
}).catch(() => undefined);

if (event === undefined) {
  throw 'Login failed';
}

// 2. Set the token on Firebase Authentication's FacebookAuthProvider in a format Firebase can use
const credential = FacebookAuthProvider.credential(event.accessToken.token);

if (type === 'new') {
// 3. Create a user with FacebookAuthProvider
const currentUser = await signInWithCredential(this.afAuth, credential)
} else {
  // (or add the login to an existing user)
  const currentUser = await linkWithCredential(this.afAuth.currentUser, credential)
}

FacebookAuthProvider is the same as new OAuthProvider('facebook.com').

  • FacebookAuthProvider
  • GithubAuthProvider
  • GoogleAuthProvider
  • TwitterAuthProvider

Firebase Authentication ships these providers, so they are easier to wire up than Sign in with Apple. Everything else follows the same pattern.

Google Auth

Use https://github.com/CodetrixStudio/CapacitorGoogleAuth. I have not implemented Google Auth in a product myself, so the code below is my best guess without running it.

// 1. Sign in with Google and obtain the login token
const googleUser = await GoogleAuth.signIn().catch(() => undefined);

if (googleUser === undefined) {
  throw 'Login failed';
}

// 2. Set the token on Firebase Authentication's GoogleAuthProvider in a format Firebase can use
const credential = GoogleAuthProvider.credential(googleUser.authentication.idToken);

if (type === 'new') {
  // 3. Create a user with GoogleAuthProvider
  const currentUser = await signInWithCredential(this.afAuth, credential)
} else {
  // (or add the login to an existing user)
  const currentUser = await linkWithCredential(this.afAuth.currentUser, credential)
}

Summary

Using the plugins above takes some work because each one needs its own native setup. Still, you can share the same code between web and native app builds, which is my preferred approach. This is more of a web-first method that relies on plugins only where needed. If you want to lean heavily on plugins instead, you can also adopt

https://github.com/robingenz/capacitor-firebase/blob/main/packages/authentication/README.md

Choose the approach that matches how you want to implement auth.

See you next time.