Saltar al contenido principal

Cómo iniciar sesión con Okta usando Capacitor

Conecta Okta a una app de Capacitor 8 con OIDC y PKCE: crea la integración nativa, configura URIs de redirección, refresh tokens, logout y soluciona errores de Okta.

Página de inicio de sesión de Okta abierta desde una app móvil Capacitor con PKCE

Para iniciar sesión con Okta en una app Capacitor, crea una Aplicación Nativa OIDC en la Okta Admin Console, registra una URI de redirección de inicio de sesión como com.example.app://oauth/okta, y ejecuta el flujo de autorización code con PKCE en un navegador del sistema. Con @capgo/capacitor-social-login configuras Okta una sola vez con tu issuer y client ID, y luego llamas a SocialLogin.login({ provider: 'oauth2', options: { providerId: 'okta' } }).

Esta guía cubre la integración de la app de Okta, las políticas del servidor de autorización, el plugin code para iOS, Android y web, el refresh de tokens, el perfil de usuario, el logout y los errores de Okta más habituales. Está pensada para Capacitor 8, a partir de octubre de 2026.

Qué necesitas

  • Una organización de Okta (Workforce Identity o Customer Identity) con acceso de admin para crear integraciones de apps.
  • Una app con Capacitor 8.
  • Tu Capacitor appId, que reutilizarás como esquema de redirección.
  • Opcionalmente, un backend API que valide los access tokens de Okta.

Cómo funciona el login de Okta en una app Capacitor

Tu app nunca muestra un formulario de contraseña. Abre la página de inicio de sesión de Okta en un navegador seguro, Okta gestiona el MFA y las políticas, y luego redirige de vuelta a tu app con un code. La app intercambia el code junto con el verificador de PKCE por los tokens.

Plataforma Navegador Configuración necesaria
iOS ASWebAuthenticationSession Nada en Info.plist
Android Chrome Custom Tabs con androidUseCustomTabs: true (WebView por defecto) Intent filter para el redirect scheme
Web Popup o redirect Trusted Origin para CORS

Prefiere Custom Tabs en Android. Okta Verify, FastPass y passkeys funcionan mejor en el navegador del sistema que en un WebView embebido, y las cookies de SSO se comparten con Chrome.

Paso 1: Crea la integración de la app de Okta

  1. En la consola de administración de Okta, ve a Aplicaciones > Aplicaciones > Crear integración de aplicación.
  2. Elige OIDC - OpenID Connect y Aplicación nativa.
  3. Dale un nombre y luego, en Tipo de concesión mantener Autorización Code y marca Token de actualización si los usuarios deben permanecer conectados.
  4. URIs de redirección de inicio de sesión: com.example.app://oauth/okta. Añade https://app.example.com/auth/callback si lanzas un build web.
  5. URIs de redirección al cerrar sesión: com.example.app://oauth/logout (y la URL web si es necesario).
  6. Asignaciones: elige quién puede usar la app. Los usuarios no asignados recibirán un error al iniciar sesión.
  7. Guarda y luego copia el ID de cliente. En Credenciales de cliente, la autenticación del cliente debe Ninguno y Requerir PKCE debe estar activada.

Okta requiere URIs de redirección nativas con un esquema de uso privado en formato de dominio inverso. Tu bundle ID o application ID sirve para esto.

Revisa el servidor de autorización en

Ve a Security > API > Authorization Servers. La mayoría de las configuraciones usan el default servidor de autorización personalizado, emisor https://your-org.okta.com/oauth2/default.

Emisor Cuándo usar
https://your-org.okta.com/oauth2/default (personalizado) Si tu propio API valida los access tokens, necesitas scopes o claims personalizados
https://your-org.okta.com (org) Solo necesitas ID tokens o llamar a las APIs de Okta

Abre la pestaña de Políticas de acceso del servidor. Debe haber una política asignada a tu app (o a All clients) con una regla que permita el Autorización Code grant, y Token de actualización si lo usas. Si falta una regla, obtendrás el error “Policy evaluation failed for this request”.

Trusted Origins para web

Si ejecutas el mismo code en la web, añade tu origen web en Seguridad > API > Orígenes de confianza con CORS marcado. Sin esto, el navegador bloqueará la solicitud del token.

Paso 2: Instalar el plugin

bun add @capgo/capacitor-social-login
bunx cap sync

Si Okta es el único proveedor, desactiva los SDKs sociales integrados en capacitor.config.ts:

plugins: {
  SocialLogin: {
    providers: { google: false, facebook: false, apple: false, twitter: false },
  },
},

Paso 3: Añadir el intent filter de redirección en Android

En android/app/src/main/AndroidManifest.xml, dentro del MainActivity actividad:

<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="com.example.app" android:host="oauth" />
</intent-filter>

MainActivity debe permanecer android:launchMode="singleTask", que es el valor por defecto de Capacitor, para que la redirección llegue a la actividad en ejecución.

Paso 4: Inicializar Okta

import { Capacitor } from '@capacitor/core';
import { SocialLogin } from '@capgo/capacitor-social-login';

const OKTA_ISSUER = 'https://your-org.okta.com/oauth2/default';
const isWeb = Capacitor.getPlatform() === 'web';

export async function initAuth() {
  await SocialLogin.initialize({
    oauth2: {
      okta: {
        appId: 'YOUR_OKTA_CLIENT_ID',
        authorizationBaseUrl: `${OKTA_ISSUER}/v1/authorize`,
        accessTokenEndpoint: `${OKTA_ISSUER}/v1/token`,
        resourceUrl: `${OKTA_ISSUER}/v1/userinfo`,
        redirectUrl: isWeb
          ? 'https://app.example.com/auth/callback'
          : 'com.example.app://oauth/okta',
        scope: 'openid profile email offline_access',
        pkceEnabled: true,
        logoutUrl: `${OKTA_ISSUER}/v1/logout`,
        postLogoutRedirectUrl: isWeb
          ? 'https://app.example.com/'
          : 'com.example.app://oauth/logout',
        androidUseCustomTabs: true,
      },
    },
  });
}

Alternativa corta: establece issuerUrl: OKTA_ISSUER y quita las URLs de los endpoints. El plugin carga /.well-known/openid-configuration y los completa. Los equipos que migren de Ionic Auth Connect pueden usar SocialLoginAuthConnect con el okta preset (issuer, clientId, redirectUrl), detallado en el guía de migración.

Paso 5: Iniciar sesión y leer el perfil

import { SocialLogin } from '@capgo/capacitor-social-login';

export async function signInWithOkta() {
  try {
    const { result } = await SocialLogin.login({
      provider: 'oauth2',
      options: { providerId: 'okta' },
    });

    const profile = result.resourceData as {
      sub: string;
      email?: string;
      name?: string;
      preferred_username?: string;
    } | null;

    return {
      accessToken: result.accessToken?.token,
      idToken: result.idToken,
      refreshToken: result.refreshToken,
      scopes: result.scope,
      profile,
    };
  } catch (error: any) {
    if (error?.code === 'USER_CANCELLED') return null;
    throw error;
  }
}

resourceData contiene el JSON devuelto por el /userinfo endpoint, así obtienes el perfil sin otra petición. Para leer los claims del ID token, usa SocialLogin.decodeIdToken({ idToken }). Esa llamada no verifica la firma.

Opciones de login que debes conocer:

  • loginHint rellena automáticamente el nombre de usuario.
  • prompt: 'login' fuerza la re-autenticación aunque haya una sesión de Okta activa.
  • additionalParameters: { idp: '0oa...' } redirige directamente a un proveedor de identidad configurado en Okta.

En web con flow: 'redirect', llama a SocialLogin.handleRedirectCallback() en la página de callback para completar el intercambio.

Paso 6: Validar los tokens de Okta en tu API

import { createRemoteJWKSet, jwtVerify } from 'jose';

const ISSUER = 'https://your-org.okta.com/oauth2/default';
const jwks = createRemoteJWKSet(new URL(`${ISSUER}/v1/keys`));

export async function verifyOktaAccessToken(token: string) {
  const { payload } = await jwtVerify(token, jwks, {
    issuer: ISSUER,
    audience: 'api://default', // the Audience value of your authorization server
  });
  return payload; // payload.uid is the Okta user ID, payload.sub the login
}

Busca el audience en el servidor de autorización Configuración tab. No valides los tokens de acceso del servidor de autorización de la organización en tu API. Okta no admite esa funcionalidad.

Paso 7: Refresh tokens

import { SocialLogin } from '@capgo/capacitor-social-login';

export async function ensureFreshOktaToken() {
  const { isLoggedIn } = await SocialLogin.isLoggedIn({ provider: 'oauth2', providerId: 'okta' });
  if (!isLoggedIn) {
    await SocialLogin.refresh({ provider: 'oauth2', options: { providerId: 'okta' } });
  }
  const { accessToken } = await SocialLogin.getAuthorizationCode({ provider: 'oauth2', providerId: 'okta' });
  return accessToken;
}

Si el refresh token ha expirado o ha sido revocado, refresh rechaza la petición. Captura ese error y redirige al usuario a la signInWithOkta().

Consulta la Token de actualización sección de la integración de la app. Con Rotar el token tras cada uso, cada refresh devuelve un nuevo refresh token y el anterior deja de funcionar tras un breve periodo de gracia. El plugin reemplaza su copia almacenada automáticamente. Si gestionas el refresh token tú mismo (por ejemplo en el Keychain mediante @capgo/capacitor-native-biometric setData, usa SocialLogin.refreshToken({ provider: 'oauth2', providerId: 'okta', refreshToken }) y guarda el valor devuelto.

Paso 8: Cerrar sesión

await SocialLogin.logout({ provider: 'oauth2', providerId: 'okta' });

El plugin limpia sus tokens almacenados y luego abre /v1/logout con id_token_hint y post_logout_redirect_uri. Okta finaliza la sesión y te redirige a tu URI de cierre de sesión, que debe estar listada en la integración de la app. En móvil, la página de cierre de sesión se abre en el navegador del sistema.

Para revocar también el refresh token en el servidor, llama al /v1/revoke endpoint de Okta desde tu backend o la app antes de cerrar sesión. Consulta nuestra guía de revocación de tokens para ver el patrón.

Solución de problemas

Error Causa Solución
invalid_request: The 'redirect_uri' parameter must be a Login redirect URI in the client app settings Redirect no registrado Añade la URI exacta a Sign-in redirect URIs
User is not assigned to the client application Falta la asignación Asigna el usuario o grupo en Assignments
Policy evaluation failed for this request Sin regla de política de acceso para este cliente o grant Añade una política y regla en el authorization server
invalid_client en el token endpoint La app es tipo Web o SPA, o el auth method no es None Usa una Native app con client authentication None
Sin refresh token Grant de Refresh Token desactivado, offline_access ausente o bloqueado por una regla Activa el grant, añade el scope y permite la regla
API rechaza el token por issuer incorrecto El token proviene del servidor de la org Usa el issuer del servidor de autorización personalizado
Web: error de CORS en /v1/token Origen no confiable Añade un Trusted Origin con CORS
Android se queda en el navegador tras el login Error de coincidencia en el Intent filter Coincide el scheme y el host con redirectUrl

Activar logsEnabled: true en la config del provider al debuguear para ver la URL de authorize y las respuestas del token en los logs nativos.

Implementando cambios de Okta

Los clientes Enterprise suelen cambiar políticas o claims tras el lanzamiento. Cambios en el cliente como scopes, manejo de claims o pantallas de error pueden enviarse con actualizaciones Live Update de Capgo en lugar de una revisión completa en la store. Las partes nativas (intent filter, nuevo scheme) aún requieren un nuevo build.

Live updates para apps Capacitor

Cuando un bug de la capa web está en producción, publica el fix a través de Capgo en lugar de esperar días a la aprobación de la app store. Los usuarios reciben la actualización en segundo plano mientras los cambios nativos siguen el flujo de revisión habitual.

Lo último de nuestro blog

Capgo te da la información clave que necesitas para crear una app móvil realmente profesional.