---
title: How to Sign In with Okta Using Capacitor
description: Learn how to add Okta authentication to your Capacitor app using the OAuth plugin with PKCE support on Android, iOS, and web.
date:
  created: 2026-03-11
  updated: 2026-07-14
authors:
  - robingenz
categories:
  - Capacitor
  - Guides
  - SDKs
links:
  - Capacitor OAuth: sdks/capacitor/oauth.md
faq: true
---

# How to Sign In with Okta Using Capacitor

[Okta](https://www.okta.com/){:target="_blank"} is a widely used identity platform that powers single sign-on (SSO) and user management for thousands of organizations. If you need to add Okta authentication to a Capacitor app, the [Capacitor OAuth plugin](../../sdks/capacitor/oauth.md) supports the Authorization Code flow with PKCE out of the box. In this guide, you'll learn how to register your app in Okta, implement sign-in and sign-out, manage tokens, and retrieve user profile data on Android, iOS, and web. This is also a great alternative to [Ionic Auth Connect](https://ionic.io/docs/auth-connect/okta){:target="_blank"} for teams looking for a lightweight, open approach.

<!-- 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>

## Bonus: Video Tutorial and Demo App

This tutorial shows the full OAuth plugin flow in a Capacitor app, including PKCE, redirect handling, token lifecycle management, and native/web behavior. The same architecture applies directly to Okta with provider-specific configuration values.

<div style="margin-top: 2rem;">
  <iframe
    width="100%"
    height="450px"
    src="https://www.youtube-nocookie.com/embed/Cr1dJNN6Urw?rel=0&modestbranding=1"
    frameborder="0"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
    referrerpolicy="strict-origin-when-cross-origin"
    allowfullscreen
  ></iframe>
</div>

- **[OAuth Demo App](https://github.com/capawesome-team/capacitor-oauth-demo){:target="_blank"}** — A practical reference implementation you can adapt to Okta by replacing issuer and client configuration.

## Prerequisites

Before getting started, make sure you have:

- An **Okta developer account**. You can [sign up for a free Okta developer account](https://developer.okta.com/signup/){:target="_blank"} if you don't already have one.
- A **Capacitor app** with the [Capacitor OAuth plugin](../../sdks/capacitor/oauth.md) installed. For installation instructions, head over to the [Installation](../../sdks/capacitor/oauth.md/#installation) section in the plugin documentation.

## Setting Up Okta

### Creating an Application

To get started, you need to register a new application in the Okta Admin Console:

1. Sign in to your [Okta Admin Console](https://login.okta.com/){:target="_blank"}.
2. Go to **Applications** > **Applications** and click **Create App Integration**.
3. Select **OIDC - OpenID Connect** as the sign-in method.
4. Choose **Native Application** as the application type and click **Next**.
5. Give your application a **Name** (e.g. `My Capacitor App`).
6. Under **Grant type**, make sure **Authorization Code** and **Refresh Token** are selected.
7. Configure the **Sign-in redirect URIs** and **Sign-out redirect URIs** (see sections below).
8. Under **Assignments**, choose the appropriate controlled access option for your use case.
9. Click **Save**.
10. On the application's **General** tab, note the **Client ID** and your **Okta domain** (e.g. `dev-123456.okta.com`). You'll need both values later.

### Configuring Sign-in Redirect URIs

Add a redirect URI for each platform your app supports. You can add multiple URIs in the **Sign-in redirect URIs** section of your application settings.

**Android and iOS**: Use a custom scheme based on your app's package name or bundle identifier:

```
com.example.app://oauth/callback
```

**Web**: Use your local development URL:

```
http://localhost:3000/oauth/callback
```

### Configuring Sign-out Redirect URIs

Similarly, configure the **Sign-out redirect URIs** so Okta knows where to send users after they log out.

**Android and iOS**:

```
com.example.app://oauth/logout
```

**Web**:

```
http://localhost:3000/oauth/logout
```

## Implementing Authentication

In the examples below, replace `{okta-domain}` with your Okta domain (e.g. `dev-123456.okta.com`) and `{client-id}` with your application's **Client ID**.

### Signing In

Kick off the OAuth flow using the [`login(...)`](../../sdks/capacitor/oauth.md#login) method. The plugin fetches Okta's OpenID Connect discovery document automatically and takes care of the PKCE challenge:

```typescript
import { Oauth } from '@capawesome-team/capacitor-oauth';

const login = async () => {
  const result = await Oauth.login({
    issuerUrl: 'https://{okta-domain}/oauth2/default',
    clientId: '{client-id}',
    redirectUrl: 'com.example.app://oauth/callback',
    scopes: ['openid', 'profile', 'email', 'offline_access'],
  });
  console.log('Access token:', result.accessToken);
  console.log('ID token:', result.idToken);
  console.log('Refresh token:', result.refreshToken);
};
```

Adding `offline_access` to the scopes ensures you receive a refresh token.

### Handling the Redirect Callback (Web)

On the web, [`login(...)`](../../sdks/capacitor/oauth.md#login) redirects the user to Okta's hosted login page. Once the user authenticates, Okta redirects them back to your app. Call [`handleRedirectCallback()`](../../sdks/capacitor/oauth.md#handleredirectcallback) when the page loads to finish the token exchange:

```typescript
import { Oauth } from '@capawesome-team/capacitor-oauth';
import { Capacitor } from '@capacitor/core';

const handleRedirectCallback = async () => {
  if (Capacitor.getPlatform() !== 'web') {
    return;
  }
  const url = new URL(window.location.href);
  if (!url.searchParams.has('code')) {
    return;
  }
  const result = await Oauth.handleRedirectCallback();
  console.log('Access token:', result.accessToken);
};

handleRedirectCallback();
```

On Android and iOS, the redirect is handled natively, so this step only applies to the web.

### Refreshing the Access Token

Access tokens are short-lived by design. Use the [`refreshToken(...)`](../../sdks/capacitor/oauth.md#refreshtoken) method to obtain a fresh access token without prompting the user to sign in again:

```typescript
import { Oauth } from '@capawesome-team/capacitor-oauth';

const refreshToken = async () => {
  const result = await Oauth.refreshToken({
    issuerUrl: 'https://{okta-domain}/oauth2/default',
    clientId: '{client-id}',
    refreshToken: 'YOUR_REFRESH_TOKEN',
  });
  console.log('New access token:', result.accessToken);
};
```

### Decoding the ID Token

Extract user profile claims from the ID token with the [`decodeIdToken(...)`](../../sdks/capacitor/oauth.md#decodeidtoken) method:

```typescript
import { Oauth } from '@capawesome-team/capacitor-oauth';

const decodeIdToken = async () => {
  const result = await Oauth.decodeIdToken({
    token: 'YOUR_ID_TOKEN',
  });
  console.log('Name:', result.payload.name);
  console.log('Email:', result.payload.email);
};
```

The token is decoded locally on the device. If you need server-side verification, validate the JWT on your backend instead.

### Signing Out

Terminate the session by calling the [`logout(...)`](../../sdks/capacitor/oauth.md#logout) method:

```typescript
import { Oauth } from '@capawesome-team/capacitor-oauth';

const logout = async () => {
  await Oauth.logout({
    issuerUrl: 'https://{okta-domain}/oauth2/default',
    idToken: 'YOUR_ID_TOKEN',
    postLogoutRedirectUrl: 'com.example.app://oauth/logout',
  });
};
```

## Fetching the User Profile

You can also retrieve the authenticated user's profile directly from Okta's `/userinfo` endpoint using the access token:

```typescript
import { Oauth } from '@capawesome-team/capacitor-oauth';

const login = async () => {
  const result = await Oauth.login({
    issuerUrl: 'https://{okta-domain}/oauth2/default',
    clientId: '{client-id}',
    redirectUrl: 'com.example.app://oauth/callback',
    scopes: ['openid', 'profile', 'email', 'offline_access'],
  });

  const response = await fetch(
    'https://{okta-domain}/oauth2/default/v1/userinfo',
    {
      headers: {
        Authorization: `Bearer ${result.accessToken}`,
      },
    },
  );
  const user = await response.json();
  console.log('Name:', user.name);
  console.log('Email:', user.email);
};
```

## FAQ

### Which platforms does this work on?

The [Capacitor OAuth plugin](../../sdks/capacitor/oauth.md) runs the Authorization Code flow with PKCE on Android, iOS, and the web from a single codebase. On Android and iOS the flow completes natively; on the web you finish it by calling [`handleRedirectCallback()`](../../sdks/capacitor/oauth.md#handleredirectcallback) on page load.

### Do I need an Okta client secret?

No. You register the app as a **Native** application, a public client that authenticates with PKCE rather than a secret — the right choice for mobile apps, where a client secret can't be stored safely.

### How do I keep the user signed in after they close the app?

Request the `offline_access` scope in [`login(...)`](../../sdks/capacitor/oauth.md#login) to receive a refresh token, store it securely — for example with the [Capacitor Secure Preferences plugin](../../sdks/capacitor/secure-preferences.md) — and exchange it for a fresh access token when needed. See [Refreshing the Access Token](#refreshing-the-access-token).

### How do I get the user's profile information?

Call your Okta org's `/userinfo` endpoint with the access token, as shown in [Fetching the User Profile](#fetching-the-user-profile). Make sure you requested the `profile` and `email` scopes during login.

### Can I use the same approach for other identity providers?

Yes. Because the plugin speaks standard OpenID Connect, the same flow works with [Auth0](./how-to-sign-in-with-auth0-using-capacitor.md), [Microsoft Entra ID](./how-to-sign-in-with-azure-entra-id-using-capacitor.md), or any compliant provider. For provider-specific SDKs, see [Google Sign-In](./how-to-sign-in-with-google-using-capacitor.md) and [Apple Sign-In](./how-to-sign-in-with-apple-using-capacitor.md).

## Related Posts

- [Alternative to the Ionic Auth Connect Plugin](./alternative-to-ionic-auth-connect-plugin.md)
- [Announcing the Capacitor OAuth Plugin](./announcing-the-capacitor-oauth-plugin.md)
- [How to Sign In with Apple Using Capacitor](./how-to-sign-in-with-apple-using-capacitor.md)
- [How to Sign In with Auth0 Using Capacitor](./how-to-sign-in-with-auth0-using-capacitor.md)

## Try Capawesome Cloud

If you're building Capacitor apps, [Capawesome Cloud](/){:target="_blank"} can help you ship faster with cloud-based native builds, over-the-air updates, and more.

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

## Conclusion

In this guide, you learned how to integrate Okta authentication into a Capacitor app using the [Capacitor OAuth plugin](../../sdks/capacitor/oauth.md). We covered creating an Okta application, configuring redirect URIs, signing users in and out, refreshing tokens, and fetching profile data. The plugin handles the OIDC and PKCE details under the hood, so you can focus on your app.

For more details, check out the full [API Reference](../../sdks/capacitor/oauth.md#api) for all available methods and options. You might also find the [How to Sign In with Azure Entra ID Using Capacitor](./how-to-sign-in-with-azure-entra-id-using-capacitor.md) guide helpful if you need to support multiple identity providers. If you have questions or run into issues, feel free to [create an issue](https://github.com/capawesome-team/capacitor-plugins/issues/new/choose){:target="_blank"} on [GitHub](https://github.com/capawesome-team/capacitor-plugins){:target="_blank"} or join the [Capawesome Discord server](https://discord.gg/VCXxSVjefW){:target="_blank"}.

To stay up to date with the latest news, subscribe to the [Capawesome newsletter](/newsletter/){:target="_blank"}.
