Naar inhoud gaan
Supastack
NL
Thema
InloggenKrijg levenslange toegang
Alle artikelen

Authenticatie & 8 betalingsgateways delen tussen Next.js, Expo mobile en Tauri v2

De twee moeilijkste naden van cross-platform SaaS: de deep-link logincallback op mobile, en één entitlement voor webbetalingen, RevenueCat IAP en desktopcheckout. Hoe één monorepo beide oplost.

Noah Zixin Zhang3 min lezen

Hoe deel je auth en betalingen tussen Next.js, Expo en Tauri?

Het hangt af van of je één identiteitsmodel en één entitlementopslag kunt behouden. Web gebruikt HttpOnly-cookiesessies; Expo slaat na de deep-link OAuth-callback een bearer token op in expo-secure-store; Tauri hergebruikt de websessie in zijn webview — allemaal gevalideerd door dezelfde Better Auth-instantie. Betalingen volgen dezelfde regel: 8 webgateways en RevenueCat mobile IAP komen samen in één idempotent webhook-ledger dat workspace-brede entitlements schrijft die elke surface leest.

De twee naden waar cross-platform SaaS scheurt

Vraag een team dat een mobiele app aan een web-SaaS heeft gelast waar het echt pijn doet — het antwoord is nooit UI. Het is identiteit en geld: de OAuth-flow die in de browser netjes terugspringt, moet via een deep link terug in de app; en de klant die op het web heeft betaald, verwacht zijn entitlement meteen in zijn telefoon.

Teams ontdekken dit meestal nadat ze twee halve oplossingen hebben geleverd: cookielogica die in WKWebView stilletjes faalt, en een RevenueCat-entitlement die vecht met het Stripe-abonnement in de webdatabase. De reparatie is architecturaal — en het is twee keer dezelfde: één identiteitsmodel, één entitlementopslag.

Eén Better Auth-instantie, drie sessietransporten

supastack houdt één Better Auth-configuratie in @supastack/auth met ingangspunten per surface. Beide web-apps (Next.js 16 en TanStack Start) gebruiken HttpOnly SameSite=Lax-cookiesessies — standaard CSRF-veilig en vriendelijk voor Server Components. De Expo-app ruilt aan het einde van de deep-link-callback de OAuth- of magic-link-voltooiing in voor een bearer token, persist dat in expo-secure-store (iOS Keychain / Android Keystore) en stuurt het als Authorization-header, gevalideerd door dezelfde auth-middleware.

Tauri's desktopshell is een enkele webview naar de web-app en erft dus direct de websessie — geen derde auth-flow om te onderhouden. De mobiele auth-gids en deep-linkgids documenteren het callbackcontract; onze web + mobile monorepo-gids toont de gedeelde clientcode.

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

Acht betalingsgateways, één contract

Elke webbetalingsprovider — Stripe, Lemon Squeezy, Polar, Creem, Dodo, Paddle, Whop en PayPal — plugt in hetzelfde @supastack/billing-contract, en elke ondertekende webhook landt eerst in een idempotent webhook_event-ledger voordat hij entitlements mag aanraken. Provider-retries en out-of-order levering worden aan de databasegrens onschuldige no-ops in plaats van supporttickets.

Mobiele in-app-aankopen voeden hetzelfde ledger via RevenueCat: storereceipts worden server-side geverifieerd en entitlements worden op de workspace geschreven, niet op het apparaat — wie op iOS betaalt, is meteen ook betaald op web en desktop. De RevenueCat-gids behandelt de App Store/Play-bedrading; idempotente billingwebhooks legt uit waarom het ledger het dragende deel is.

Het entitlementmodel dat synchronisatie saai maakt

Waarom het saai blijft: entitlements leven op de workspace en worden server-side opgelost. Geen enkele client houdt 'betaald' vast — het web vraagt het aan de sessie, mobile aan de API, desktop aan de web-app — en alle drie krijgen hetzelfde antwoord omdat er maar één record is om te antwoorden.

Aankoop herstellen op een nieuwe telefoon, een Stripe-verlenging op het web, een Agency-seat toegevoegd in het dashboard — elk is een write in dezelfde entitlementregels die elke surface bij de volgende vraag leest. Er is geen sync-engine om te bouwen omdat er niets is om te synchroniseren.

PlatformSessietransportBetalingspadEntitlements gelezen uit
Next.js 16 webHttpOnly-cookieElk van de 8 gateways → webhook-ledgerGedeelde Postgres-entitlementregels
TanStack Start webHttpOnly-cookieDezelfde adapters, hetzelfde ledgerGedeelde Postgres-entitlementregels
Expo iOS / AndroidBearer token in expo-secure-storeRevenueCat IAP → servergeverifieerde receiptDezelfde regels (via getypte API)
Tauri 2 desktopWebsessie in de webviewWebcheckout binnen de shellDezelfde regels (via web-app)
MV3-extensieWorkspace-API-key— (leest workspacedata)Dezelfde regels (via /api/v1)

Wat je niet meer hoeft te bouwen

Omgerekend naar avonden werk is dat het verschil tussen fundament en featurelijst: de deep-link auth-return, SecureStore-tokenpersistentie, acht replay-veilige webhook-integraties, App Store-receiptverificatie en een entitlementmodel dat zich tussen apparaten nooit tegenspreekt. Allemaal geleverd, getest (693+ tests zonder credentials) en gedocumenteerd.

De $299 Full Bundle bevat alle surfaces in één repo — seataantallen en agencyniveaus op de prijspagina.

FAQ: auth & betalingen delen over platforms

Vragen die teams stellen voordat ze op de uniforme stack committeren:

  • Loggen mobiele gebruikers apart van het web in?, Nee. De OAuth- of magic-linkflow keert via deep link terug in de app en geeft dezelfde sessie uit; dezelfde Better Auth-instantie geeft uit, dus web en mobile antwoorden hetzelfde op 'wie ben je'.
  • Wat als iemand op iOS betaalt maar de web-app gebruikt?, RevenueCat levert de aankoop server-side; het entitlement wordt in dezelfde workspaceregels geschreven die het web leest, en de web-app toont betaald bij het volgende verzoek.
  • Kun je alleen met web beginnen en later apps toevoegen?, Ja — auth en billing leven in de gedeelde packages, dus de mobile- en desktop-apps erven ze zodra je die surfaces aanzet.
  • Heeft de Tauri-app een eigen checkout nodig?, Nee — de desktopshell hergebruikt sessie en checkout van de web-app in zijn webview; er is geen tweede betalingssurface om te verdedigen.

Je volgende product begint hier.

Betaal één keer. Blijf winstgevende producten bouwen.