---
title: "How to Add Authentication to a Capacitor App"
description: Every way to authenticate users in a Capacitor app — social sign-in, Firebase, OAuth/OIDC, passkeys, Better Auth — plus biometrics and session storage.
date:
  created: 2026-09-15
  updated: 2026-09-15
authors:
  - djabif
categories:
  - Capacitor
  - Guides
faq: true
---

# How to Add Authentication to a Capacitor App

Capacitor authentication has several first-party options, and most apps end up combining more than one: native sign-in with Apple, Google, or Facebook; Firebase Authentication if you're already on Firebase; the generic OAuth plugin for enterprise identity providers like Auth0, Okta, or Microsoft Entra ID; passkeys for passwordless sign-in; or Better Auth if you'd rather self-host the whole thing. You don't need a custom native plugin to reach any of these; a first-party plugin covers each one.

This post walks through every method, what it costs, and which one fits your app, then covers the two questions every method eventually runs into: how to gate access with biometrics, and where to store the session afterward.

<!-- more -->

<div class="capawesome-z29o10a">
  <a href="/" target="_blank">
    <img alt="Build and deploy your Capacitor app with Capawesome Cloud" src="https://capawesome.io/assets/banners/cloud-build-and-deploy-capacitor-apps.png?t=1" />
  </a>
</div>

**Key takeaways:**

- Five ways to authenticate a user: native social sign-in (Apple, Google, Facebook), Firebase Authentication, generic OAuth 2.0 / OpenID Connect, passkeys (WebAuthn), and Better Auth for a self-hosted backend.
- Apple Sign-In, Google Sign-In, Facebook Sign-In, and Passkeys are free and open source. The OAuth plugin, Biometrics, Secure Preferences, and Vault are [Capawesome Insiders](../../insiders/index.md) plugins.
- Biometrics doesn't authenticate a user on its own. It's a local device gate that unlocks something you already stored, like a session token in Vault.
- The OAuth plugin's Android setup needs one `manifestPlaceholders` entry in `build.gradle`; the iOS redirect URI must exactly match what you register with your provider, trailing slash included.
- Passkeys need domain verification before they work: an `apple-app-site-association` file on iOS, a Digital Asset Links file on Android.
- Ionic Auth Connect is discontinued; the Capacitor OAuth plugin is the direct replacement for OAuth 2.0 and OpenID Connect flows.

## At a glance

| Method | Best for | License | Providers | Guide |
| --- | --- | --- | --- | --- |
| **Native social sign-in** | Consumer apps, no backend | Free | Apple, Google, Facebook | [Apple](./how-to-sign-in-with-apple-using-capacitor.md), [Google](./how-to-sign-in-with-google-using-capacitor.md) |
| **Passkeys** | Passwordless sign-in | Free | Any WebAuthn relying party | [Docs](../../sdks/capacitor/passkeys.md) |
| **Firebase Authentication** | Apps already using Firebase | Free | Email, phone, Google, Apple, Facebook, and more | [Guide](./capacitor-firebase-authentication-guide.md) |
| **OAuth / OpenID Connect** | Enterprise SSO, Auth Connect migration | Insiders | Auth0, Okta, Azure Entra ID, Cognito, OneLogin | [Docs](../../sdks/capacitor/oauth.md) |
| **Better Auth** | Self-hosted, open-source backend | Free core (paid plugins for native social flows) | Any provider Better Auth supports | [Guide](./how-to-use-better-auth-in-capacitor-apps.md) |

## The typical auth flow

Every method in this post implements the same six steps; what changes between them is who performs each one.

1. **The user triggers sign-in.** A "Continue with Apple" button, an email form, a passkey prompt.
2. **The app hands off to the identity provider.** A native sheet for Apple or Google, a secure system browser with PKCE for OAuth providers, the platform's WebAuthn dialog for passkeys. What no modern flow does is collect a third-party password inside your own UI: the providers restrict it, and users have learned to distrust it.
3. **The provider returns a credential.** An ID token, an authorization code the plugin exchanges for tokens, or a signed WebAuthn assertion, delivered back through the plugin or the redirect your app registered.
4. **Your backend verifies it and creates a session.** Firebase does this step for you; with the OAuth plugin, your API validates the token it receives; with Better Auth, your own server issues the session.
5. **The app stores the session on the device.** Encrypted and silently restorable for the common case, or behind an explicit unlock for sensitive data. This is where Secure Preferences and Vault come in, covered below.
6. **Later launches restore, refresh, and eventually sign out.** Restore the stored session without showing a login screen, refresh tokens silently, optionally gate the restore behind a biometric check, and clear everything on sign-out.

<figure markdown>
  ![The six steps of Capacitor authentication, from the sign-in trigger to session storage and restore](../../assets/images/posts/how-to-add-authentication-to-a-capacitor-app/typical-auth-flow.svg)
  <figcaption>The six steps every Capacitor authentication method shares</figcaption>
</figure>

The method sections that follow each cover steps 2 through 4 for one option. Steps 5 and 6 are the same job regardless of the method you pick, which is why biometrics and session storage get their own sections at the end.

## Native social sign-in

If your app doesn't need a backend beyond "who is this user," native sign-in is the simplest path: one plugin per provider, each wrapping the platform's own SDK so the sign-in sheet looks and behaves like a native one instead of a browser popup.

- **[Apple Sign-In](../../sdks/capacitor/apple-sign-in.md)** is required by Apple if your app offers any other third-party sign-in option and targets iOS, per App Store Review Guideline 4.8. See [How to Sign In with Apple Using Capacitor](./how-to-sign-in-with-apple-using-capacitor.md).
- **[Google Sign-In](../../sdks/capacitor/google-sign-in.md)** covers the most common social login on Android specifically. See [How to Sign In with Google Using Capacitor](./how-to-sign-in-with-google-using-capacitor.md). One frequent setup mistake: the web client ID you pass as `serverClientId` and your Android client ID must come from the same Google Cloud project, or sign-in fails silently on Android.
- **[Facebook Sign-In](../../sdks/capacitor/facebook-sign-in.md)** includes Limited Login support on iOS. See the plugin documentation for setup; there's no dedicated walkthrough post for this one yet.

All three are free and open source, so this is the path with no licensing cost at all, whichever combination you pick.

## Sign in with passkeys

Passkeys implement the [WebAuthn](https://www.w3.org/TR/webauthn-3/){:target="_blank"} standard: a public/private key pair replaces a password, the private key never leaves the device's secure hardware, and there's nothing for a phishing page to steal. The [Capacitor Passkeys plugin](../../sdks/capacitor/passkeys.md) creates and authenticates with passkeys on Android 9+, iOS 15+, and any browser with WebAuthn support, and it's free and open source.

Before passkeys work, both platforms need to prove your app owns your domain:

- **iOS**: add the Associated Domains capability with a `webcredentials` service type, and host an `apple-app-site-association` file at `https://<your-domain>/.well-known/apple-app-site-association`.
- **Android**: host a Digital Asset Links file at `https://<your-domain>/.well-known/assetlinks.json`, granting the `common.get_login_creds` permission to your app's SHA-256 signing certificate fingerprint.

Skip this step and sign-in fails with a `DOMAIN_NOT_ASSOCIATED` error on both platforms. Once it's in place, `createPasskey()` registers a new passkey and `getPasskey()` authenticates with an existing one; `isAvailable()` lets you check WebAuthn support before showing the option, so you can offer it as a choice alongside a fallback rather than a hard requirement.

## Firebase Authentication

If your app already uses (or will use) other Firebase services, [Firebase Authentication](../../sdks/capacitor/firebase/authentication.md) is worth defaulting to before reaching for a standalone plugin: the user ID it produces is what Firestore security rules, Crashlytics reports, and Cloud Functions calls all key off, so wiring it up first saves rework as you add the rest of the suite. It supports email/password, phone, and social providers (Google, Apple, Facebook, and more) behind one API, free and open source like the rest of the Firebase plugin family.

See [Firebase Authentication in Capacitor: Setup & Best Practices](./capacitor-firebase-authentication-guide.md) for the full setup, and [How to Use Firebase in a Capacitor App](./how-to-use-firebase-in-a-capacitor-app.md) for how it fits with Firestore, Storage, and the rest of the suite. If you're not planning to use any other Firebase service, the standalone social sign-in plugins or the OAuth plugin below add less overhead than pulling in a whole Firebase project for sign-in alone.

## OAuth and OpenID Connect

The [Capacitor OAuth plugin](../../sdks/capacitor/oauth.md) implements the OAuth 2.0 Authorization Code flow with PKCE and OpenID Connect discovery, and it's the plugin behind every enterprise-SSO integration on this site: Auth0, Okta, Microsoft Entra ID, Amazon Cognito, OneLogin, or any other standards-compliant provider. It's also the direct replacement for [Ionic Auth Connect](./alternative-to-ionic-auth-connect-plugin.md), which reaches end of life on December 31, 2027; the plugin covers the same OAuth 2.0 and OpenID Connect ground Auth Connect did.

Setup needs one piece of redirect configuration per platform:

- **Android**: register your redirect scheme in `android/app/build.gradle`:

  ```groovy
  android {
    defaultConfig {
      manifestPlaceholders = [appAuthRedirectScheme: "com.example.app"]
    }
  }
  ```

  Replace `com.example.app` with your own scheme.

- **iOS**: no separate manifest entry, but the redirect URI you register with your provider must exactly match what the plugin sends, including any trailing slash. A mismatch here is the most common cause of a login that silently fails after the provider's consent screen, or of Google's "Error 400: redirect_uri_mismatch" page.

<figure markdown>
  ![OAuth login flow in a Capacitor app on Android, from the sign-in button through the secure browser and back into the app](../../assets/images/posts/how-to-add-authentication-to-a-capacitor-app/oauth-demo-android.gif){ width="300" }
  <figcaption>The OAuth plugin's full login round trip on Android</figcaption>
</figure>

Provider-specific walkthroughs cover the exact `issuerUrl` and `clientId` values for each: [Auth0](./how-to-sign-in-with-auth0-using-capacitor.md), [Okta](./how-to-sign-in-with-okta-using-capacitor.md), and [Microsoft Entra ID](./how-to-sign-in-with-azure-entra-id-using-capacitor.md). If your organization is already standardized on Microsoft 365 and needs app-level device management on top of sign-in, the [Intune plugin](../../sdks/capacitor/intune.md) adds MSAL authentication with Intune app protection policies on top, which is a narrower and more Microsoft-specific tool than the general OAuth plugin.

If your backend is [Supabase](https://supabase.com/){:target="_blank"}, its auth service is itself OAuth/OIDC-compatible, so the OAuth plugin works for its social providers, and Supabase's own JavaScript SDK handles email/password and magic-link flows directly, since those don't need a native bridge.

Unlike the native social plugins, the OAuth plugin is a [Capawesome Insiders](../../insiders/index.md) plugin.

## Better Auth for self-hosting

[Better Auth](https://www.better-auth.com/){:target="_blank"} handles authentication in TypeScript on infrastructure you run yourself, rather than a vendor's hosted identity service. Its JavaScript SDK runs directly in your Capacitor app's WebView for standard flows like email/password, since Capacitor apps are web apps under the hood. You only reach for a native plugin for the parts a WebView genuinely can't do well: social sign-in flows that need a native browser sheet, which is where the Apple Sign-In, Google Sign-In, and OAuth plugins come back in.

See [How to Use Better Auth in Capacitor Apps](./how-to-use-better-auth-in-capacitor-apps.md) for the full setup. This path is worth it if you want to own your user data and auth logic outright rather than depend on Firebase, Auth0, or another hosted provider, at the cost of running and securing that backend yourself.

## What biometrics protects

Face ID, fingerprint, and iris scanning don't identify a user to your backend on their own. They're a local device gate that confirms the person holding the phone is the one it's enrolled to, then unlocks something you already have, most often a session token or credential stored on the device. Pair biometrics with an actual sign-in method above; it's the lock on the door, not the identity behind it.

The [Capacitor Biometrics plugin](../../sdks/capacitor/biometrics.md) (Insiders) wraps Face ID, Touch ID, fingerprint, and iris recognition (Android only) behind one `authenticate()` call. Check `isAvailable()` and `isEnrolled()` before calling it, since a device can lack biometric hardware entirely or have it disabled. Useful options include `allowDeviceCredential` to fall back to the device PIN or password when biometrics fail, and `androidBiometricStrength` to require `Strong` (Class 3) hardware-backed sensors over `Weak` ones. iOS needs an `NSFaceIDUsageDescription` entry in `Info.plist` explaining why your app wants Face ID access; without it, the authentication call crashes at runtime rather than failing gracefully. See [Exploring the Capacitor Biometrics API](./exploring-the-capacitor-biometrics-api.md) for the full walkthrough.

<figure>
  <video width="300" autoplay loop muted playsinline>
    <source src="/docs/assets/videos/posts/how-to-add-authentication-to-a-capacitor-app/biometrics-demo.mp4" type="video/mp4">
  </video>
  <figcaption>The Biometrics plugin's authenticate() prompt in action</figcaption>
</figure>

## Storing the session afterward

Every method above ends the same way: you have a token, and you need to keep it somewhere the app can retrieve on the next launch without asking the user to sign in again. Two Insiders plugins cover this, and they solve different problems.

**[Secure Preferences](../../sdks/capacitor/secure-preferences.md)** is a transparent encrypted key-value store your app reads and writes anytime, no extra prompt required. It's the right default for a session token or refresh token: encrypted at rest, but available the moment your app needs it.

**[Vault](../../sdks/capacitor/vault.md)** is stricter: every read or write requires the vault to be explicitly unlocked first, via `unlock()` with biometrics or a device passcode, and `lock()` clears the decryption key from memory. That extra friction is the point for data that should require a deliberate user action to access, the way a password manager or an authenticator app's secrets should, rather than data your app needs quietly in the background. This is where biometrics from the section above gets used: the `authenticate()` call and Vault's `unlock()` are the same underlying gesture serving two different plugins.

**[Password Autofill](../../sdks/capacitor/password-autofill.md)** (free) is a smaller, complementary piece: after a successful in-app login, it saves the credentials to the platform's own credential store (iCloud Keychain, Google Password Manager), so the *next* app or website that uses those credentials can offer to autofill them too. It doesn't replace Secure Preferences or Vault; it's a UX courtesy on top of whichever one you use.

## Choosing an authentication method

Which authentication method you should use follows from what your app already has, not from what looks most modern:

- **Building a consumer app with no backend of your own?** Native social sign-in (Apple, Google, Facebook) or passkeys, both free, get a user identity with the least setup.
- **Already using or planning to use Firebase for anything else?** Firebase Authentication first; the user ID it produces is what the rest of the Firebase suite depends on.
- **Need enterprise SSO, or migrating off Ionic Auth Connect?** The OAuth plugin is the only option here and covers Auth0, Okta, Azure Entra ID, and other standards-compliant providers.
- **Want to own your auth backend instead of depending on a vendor?** Better Auth, backed by the same native plugins for social flows.
- **Need to protect access to already-stored data, like a saved session or a secrets vault?** That's Biometrics plus Secure Preferences or Vault, not a login method on its own.

One case needs no plugin at all: plain email/password against your own API. A Capacitor app is a web app, so that's an ordinary `fetch` call from your login form to your backend. The Capacitor-specific work only starts after the response arrives, at steps 5 and 6 of the flow above: store the session in [Secure Preferences](../../sdks/capacitor/secure-preferences.md) rather than `localStorage` (which the OS can clear and never encrypts), and let [Password Autofill](../../sdks/capacitor/password-autofill.md) save the credentials to the platform's credential store.

## FAQ

### Can I use more than one authentication method in the same app?

Yes, and most production apps do: Firebase Authentication or the OAuth plugin for the actual sign-in, paired with Biometrics as a re-authentication gate on app resume, and Password Autofill so credentials save to the platform's credential store afterward. Nothing here is mutually exclusive.

### Why does Google Sign-In fail on Android but work on the web?

The most common cause is that the web client ID you configured as `serverClientId` and your Android client ID come from different Google Cloud projects. Google Sign-In requires both to belong to the same project; check the Google Cloud Console credentials page for both client IDs before debugging further.

### Is biometric authentication the same as a password?

No. Biometrics unlocks something already stored on the device, like a session token in Vault; it doesn't create or verify a backend identity by itself. If your app has no other sign-in method and no stored session to unlock, adding Biometrics alone doesn't authenticate anyone.

### What happened to Ionic Auth Connect?

Ionic discontinued its commercial products, including Auth Connect (`@ionic-enterprise/auth`), and it reaches end of life on December 31, 2027. The Capacitor OAuth plugin covers the same OAuth 2.0 and OpenID Connect ground; see [Alternative to the Ionic Auth Connect Plugin](./alternative-to-ionic-auth-connect-plugin.md) for the migration path.

### Do these plugins support Capacitor 8?

Yes. The current releases of every first-party plugin in this post (the sign-in plugins, Passkeys, OAuth, Biometrics, Secure Preferences, Vault, and the Firebase Authentication plugin) list Capacitor 8 or later under active support in their compatibility tables.

### Can I add two-factor authentication to a Capacitor app?

Yes, and it usually happens at the identity provider rather than in your app code. Enterprise providers like Okta and Microsoft Entra ID enforce MFA inside the browser flow the OAuth plugin opens, with no app changes. Firebase Authentication supports phone-based second factors on its side, and the plugin reports the session's second factor via `signInSecondFactor`. A biometric prompt in your app is not a second factor by itself; it gates access to the device-stored session, not the account.

### Does Apple require anything special if my app has account creation?

Yes: App Store Review Guideline 5.1.1(v) requires that any app supporting account creation also lets users initiate account deletion from inside the app. Whichever sign-in method you pick, plan the deletion flow before submission, since this is a common review rejection.

### Do these authentication plugins work on the web, not just Android and iOS?

Most do. Apple Sign-In, Google Sign-In, the OAuth plugin, Passkeys, and Firebase Authentication all have a web implementation. Facebook Sign-In, Biometrics, and Vault are Android/iOS only, since they depend on native platform capabilities the web doesn't expose the same way.

## Try Capawesome Cloud

[Try Capawesome Cloud Free](https://capawesome.io){ .md-button .md-button--primary }

## Conclusion

Default to the free options first (native social sign-in, passkeys, or Firebase Authentication if you're already there), and reach for the OAuth plugin only when you need enterprise SSO or a real replacement for a discontinued Auth Connect setup. Whichever method you pick, decide separately how you'll store the resulting session: Secure Preferences for the common case, Vault when access should require a deliberate biometric or passcode check.

For the full setup of any of these, start with the [Capacitor OAuth Plugin documentation](../../sdks/capacitor/oauth.md) or [Firebase Authentication in Capacitor: Setup & Best Practices](./capacitor-firebase-authentication-guide.md). Questions about your specific setup? Join the [Capawesome Discord server](https://discord.gg/VCXxSVjefW){:target="_blank"}, and subscribe to the [Capawesome newsletter](https://capawesome.io/newsletter/){:target="_blank"} for more guides like this one.
