Pular para o conteúdo
Supastack
PT
Tema
EntrarObter acesso vitalício
Todos os artigos

Compartilhando autenticação e 8 gateways de pagamento entre Next.js, Expo mobile e Tauri v2

As duas costuras mais duras do SaaS multi-plataforma: o callback de login por deep link no mobile e um único entitlement para pagamentos web, RevenueCat IAP e checkout desktop. Como um monorepo resolve as duas.

Noah Zixin Zhang3 min de leitura

Como compartilhar auth e pagamentos entre Next.js, Expo e Tauri?

Depende de manter um único modelo de identidade e um único armazenamento de entitlements. A web usa sessões por cookie HttpOnly; o Expo guarda um bearer token no expo-secure-store após o callback OAuth por deep link; o Tauri reusa a sessão web dentro da sua webview — todas validadas pela mesma instância Better Auth. Os pagamentos seguem a mesma regra: 8 gateways web e RevenueCat IAP mobile convergem num ledger de webhooks idempotente que escreve entitlements em nível de workspace lidos por cada superfície.

As duas costuras onde o SaaS multi-plataforma rasga

Pergunte a qualquer equipe que soldou um app mobile num SaaS web onde dói de verdade — a resposta nunca é UI. É identidade e dinheiro: o fluxo OAuth que volta limpo no navegador precisa voltar para o app via deep link, e o cliente que pagou na web espera seu entitlement no telefone na hora.

As equipes geralmente descobrem depois de lançar duas meias-soluções: lógica de cookies que falha em silêncio dentro do WKWebView e um entitlement RevenueCat que briga com a assinatura Stripe no banco web. O conserto é arquitetural — e é o mesmo duas vezes: um modelo de identidade, um armazenamento de entitlements.

Uma instância Better Auth, três transportes de sessão

O supastack mantém uma única configuração Better Auth em @supastack/auth com pontos de entrada por superfície. Os dois apps web (Next.js 16 e TanStack Start) usam sessões de cookie HttpOnly SameSite=Lax — seguras contra CSRF por padrão e amigáveis a Server Components. O app Expo troca a conclusão do OAuth ou magic link no fim do callback deep link por um bearer token, o persiste no expo-secure-store (iOS Keychain / Android Keystore) e o envia como header Authorization, validado pelo mesmo middleware de auth.

O shell desktop do Tauri é uma webview única apontando para o app web, então herda a sessão web diretamente — sem um terceiro fluxo de auth para manter. O guia de auth mobile e o guia de deep links documentam o contrato de callback; nosso guia de monorepo web + mobile mostra o código cliente compartilhado.

// 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.

Oito gateways de pagamento, um contrato

Todo provedor de pagamento web — Stripe, Lemon Squeezy, Polar, Creem, Dodo, Paddle, Whop e PayPal — se encaixa no mesmo contrato @supastack/billing, e cada webhook assinado cai primeiro num ledger webhook_event idempotente antes de poder tocar entitlements. Retries de provedores e entregas fora de ordem viram no-ops inofensivos na fronteira do banco, não tickets de suporte.

As compras in-app mobile entram no mesmo ledger via RevenueCat: os recibos das lojas são verificados no servidor e os entitlements escritos no workspace, não no dispositivo — quem paga no iOS já está pago na hora também na web e no desktop. O guia RevenueCat cobre a fiação App Store / Play; webhooks de billing idempotentes explica por que o ledger é a peça estrutural.

O modelo de entitlements que torna a sincronização entediante

Por que fica entediante: os entitlements vivem no workspace e são resolvidos no servidor. Nenhum cliente guarda o estado «pago» — a web pergunta à sessão, o mobile à API, o desktop ao app web — e os três recebem a mesma resposta porque só há um registro capaz de responder.

Restaurar compra num telefone novo, renovação Stripe na web, um assento Agency adicionado no dashboard — cada um é uma escrita nas mesmas linhas de entitlement que cada superfície lê na próxima consulta. Não há motor de sync para construir porque não há nada para sincronizar.

SuperfícieTransporte de sessãoCaminho de pagamentoEntitlements lidos de
Next.js 16 webCookie HttpOnlyQualquer um dos 8 gateways → ledger de webhooksLinhas de entitlement Postgres compartilhadas
TanStack Start webCookie HttpOnlyMesmos adaptadores, mesmo ledgerLinhas de entitlement Postgres compartilhadas
Expo iOS / AndroidBearer token no expo-secure-storeRevenueCat IAP → recibo verificado no servidorMesmas linhas (via API tipada)
Tauri 2 desktopSessão web dentro da webviewCheckout web dentro do shellMesmas linhas (via app web)
Extensão MV3Chave de API workspace— (lê dados do workspace)Mesmas linhas (via /api/v1)

O que você deixa de construir

Convertido em noites de trabalho, essa é a diferença entre fundação e lista de features: o retorno de auth por deep link, a persistência de token no SecureStore, oito integrações de webhook à prova de replay, a verificação de recibos da App Store e um modelo de entitlements que nunca se contradiz entre dispositivos. Tudo entregue, testado (693+ testes sem credenciais) e documentado.

O Full Bundle de $299 contém todas as superfícies num repo — números de assentos e níveis de agência na página de preços.

FAQ: compartilhar auth e pagamentos entre plataformas

Perguntas que equipes fazem antes de se comprometer com a stack unificada:

  • Usuários mobile fazem login separado da web?, Não. O fluxo OAuth ou magic link retorna ao app por deep link e emite a mesma sessão; quem emite é a mesma instância Better Auth, então web e mobile respondem igual a «quem é você».
  • E quem paga no iOS mas usa o app web?, A RevenueCat entrega a compra no lado servidor; o entitlement é escrito nas mesmas linhas de workspace que a web lê, e o app web mostra «pago» na próxima requisição.
  • Dá para começar só com web e adicionar apps depois?, Sim — auth e billing vivem nos pacotes compartilhados, então os apps mobile e desktop os herdam quando você liga essas superfícies.
  • O app Tauri precisa de checkout próprio?, Não — o shell desktop reusa sessão e checkout do app web dentro da sua webview; não há uma segunda superfície de pagamento para defender.

O teu próximo produto começa aqui.

Pague uma vez. Continue criando produtos lucrativos.