Saltar al contenido
Supastack
ES
Tema
Iniciar sesiónObtén acceso de por vida
Todos los artículos

Compartir autenticación y 8 pasarelas de pago entre Next.js, Expo móvil y Tauri v2

Las dos costuras más duras del SaaS multi-plataforma: el callback de login por deep link en móvil y un único entitlement para pagos web, RevenueCat IAP y checkout de desktop. Cómo un monorepo resuelve ambas.

Noah Zixin Zhang4 min de lectura

¿Cómo compartir auth y pagos entre Next.js, Expo y Tauri?

Depende de mantener un solo modelo de identidad y un solo almacén de entitlements. La web usa sesiones con cookie HttpOnly; Expo guarda un bearer token en expo-secure-store tras el callback OAuth por deep link; Tauri reutiliza la sesión web dentro de su webview — todas validadas por la misma instancia Better Auth. Los pagos siguen la misma regla: 8 pasarelas web y RevenueCat IAP móvil desembocan en un ledger de webhooks idempotente que escribe entitlements a nivel workspace que cada superficie lee.

Las dos costuras donde se rompe el SaaS multi-plataforma

Pregunta a cualquier equipo que haya soldado una app móvil a un SaaS web dónde duele de verdad — la respuesta nunca es la UI. Son la identidad y el dinero: el flujo OAuth que vuelve limpio en el navegador debe volver a la app vía deep link, y el cliente que pagó en la web espera ver su entitlement en el teléfono al instante.

Los equipos suelen descubrirlo después de lanzar dos medias soluciones: lógica de cookies que falla en silencio dentro de WKWebView y un entitlement de RevenueCat que pelea con la suscripción Stripe en la base web. La reparación es arquitectónica — y es la misma dos veces: un modelo de identidad, un almacén de entitlements.

Una instancia Better Auth, tres transportes de sesión

supastack mantiene una única configuración Better Auth en @supastack/auth con puntos de entrada por superficie. Las dos apps web (Next.js 16 y TanStack Start) usan sesiones de cookie HttpOnly SameSite=Lax — seguras frente a CSRF por defecto y compatibles con Server Components. La app Expo canjea la finalización del OAuth o magic link al final del callback deep link por un bearer token, lo persiste en expo-secure-store (iOS Keychain / Android Keystore) y lo envía como cabecera Authorization, validado por el mismo middleware de auth.

El shell desktop de Tauri es una única webview apuntando a la app web, así que hereda la sesión web directamente — sin un tercer flujo de auth que mantener. La guía de auth móvil y la guía de deep links documentan el contrato de callback; nuestra guía de monorepo web + móvil muestra el código cliente compartido.

// packages/auth/src/client.ts — one client, two storages
import { createAuthClient } from "better-auth/react";
import { expoClient } from "@better-auth/expo/client";

export function createCrossPlatformAuthClient(baseURL: string, storage?: any) {
  return createAuthClient({
    baseURL,
    plugins: storage ? [expoClient({ scheme: "myapp", storage })] : [],
  });
}

// Web: cookie session.  Mobile: bearer token in SecureStore.
// Desktop: the web app's own session inside the Tauri webview.

Ocho pasarelas de pago, un contrato

Cada proveedor de pago web — Stripe, Lemon Squeezy, Polar, Creem, Dodo, Paddle, Whop y PayPal — se enchufa al mismo contrato @supastack/billing, y cada webhook firmado aterriza primero en un ledger webhook_event idempotente antes de poder tocar entitlements. Los reintentos de proveedores y las entregas desordenadas se convierten en no-ops inofensivos en la frontera de la base de datos, no en tickets de soporte.

Las compras in-app móviles entran al mismo ledger vía RevenueCat: los recibos de las stores se verifican en servidor y los entitlements se escriben en el workspace, no en el dispositivo — quien paga en iOS está pagado también al instante en web y desktop. La guía de RevenueCat cubre el cableado App Store / Play; los webhooks de billing idempotentes explican por qué el ledger es la pieza que soporta peso.

El modelo de entitlements que vuelve aburrida la sincronización

Por qué se mantiene aburrido: los entitlements viven en el workspace y se resuelven en servidor. Ningún cliente guarda el «pagado» — la web pregunta a la sesión, el móvil a la API, el desktop a la app web — y los tres obtienen la misma respuesta porque solo hay un registro que pueda responder.

Restaurar compra en un teléfono nuevo, renovación Stripe en la web, un asiento Agency añadido en el dashboard — cada uno es una escritura en las mismas líneas de entitlement que cada superficie lee en su próxima consulta. No hay motor de sync que construir porque no hay nada que sincronizar.

SuperficieTransporte de sesiónRuta de pagoEntitlements leídos de
Next.js 16 webCookie HttpOnlyCualquiera de las 8 pasarelas → ledger de webhooksLíneas de entitlement Postgres compartidas
TanStack Start webCookie HttpOnlyMismos adaptadores, mismo ledgerLíneas de entitlement Postgres compartidas
Expo iOS / AndroidBearer token en expo-secure-storeRevenueCat IAP → recibo verificado en servidorMismas líneas (vía API tipada)
Tauri 2 desktopSesión web dentro de la webviewCheckout web dentro del shellMismas líneas (vía app web)
Extensión MV3Clave API workspace— (lee datos del workspace)Mismas líneas (vía /api/v1)

Lo que te ahorras construir

Traducido a noches de trabajo, esa es la diferencia entre base y lista de features: el retorno de auth por deep link, la persistencia del token en SecureStore, ocho integraciones de webhooks a prueba de replays, la verificación de recibos de App Store y un modelo de entitlements que nunca se contradice entre dispositivos. Todo entregado, testeado (693+ tests sin credenciales) y documentado.

El Full Bundle de $299 contiene todas las superficies en un repo — asientos y niveles de agencia en la página de precios.

FAQ: compartir auth y pagos entre plataformas

Preguntas que hacen los equipos antes de comprometerse con el stack unificado:

  • ¿Los usuarios móviles inician sesión aparte de la web?, No. El flujo OAuth o magic link vuelve a la app por deep link y emite la misma sesión; la instancia Better Auth emisora es la misma, así que web y móvil responden igual a «quién eres».
  • ¿Y alguien que paga en iOS pero usa la app web?, RevenueCat entrega la compra en el lado servidor; el entitlement se escribe en las mismas líneas de workspace que la web lee, y la app web muestra «pagado» en la siguiente petición.
  • ¿Se puede empezar solo con web y añadir apps después?, Sí — auth y billing viven en los paquetes compartidos, así que las apps móvil y desktop los heredan cuando activas esas superficies.
  • ¿La app Tauri necesita su propio checkout?, No — el shell desktop reutiliza la sesión y el checkout de la app web dentro de su webview; no hay una segunda superficie de pago que blindar.

Tu próximo producto empieza aquí.

Paga una vez. Sigue creando productos rentables.