Aller au contenu
Supastack
FR
Thème
Se connecterObtenir l'accès à vie
Tous les articles

Partager l'authentification et 8 passerelles de paiement entre Next.js, Expo mobile et Tauri v2

Les deux soudures les plus dures d'un SaaS multi-plateforme : le callback de connexion par deep link sur mobile, et l'unicité des entitlements entre paiements web, RevenueCat IAP et checkout desktop. Comment un monorepo résout les deux.

Noah Zixin Zhang3 min de lecture

Comment partager l'auth et les paiements entre Next.js, Expo et Tauri ?

Tout dépend de votre capacité à garder un seul modèle d'identité et un seul magasin d'entitlements. Le web utilise des sessions par cookie HttpOnly ; Expo stocke un bearer token dans expo-secure-store après le callback OAuth par deep link ; Tauri réutilise la session web dans sa webview — toutes validées par la même instance Better Auth. Les paiements suivent la même règle : 8 passerelles web et RevenueCat IAP mobile convergent vers un ledger de webhooks idempotent qui écrit des entitlements au niveau workspace, lus par chaque surface.

Les deux soudures où le SaaS multi-plateforme se déchire

Demandez à une équipe qui a soudé une app mobile sur un SaaS web où ça fait vraiment mal — la réponse n'est jamais l'UI. C'est l'identité et l'argent : le flux OAuth qui revient proprement dans le navigateur doit revenir dans l'app via un deep link ; et le client qui a payé sur le web attend que ses droits apparaissent aussitôt dans son téléphone.

Les équipes s'en rendent compte en général après avoir livré deux demi-solutions : une logique de cookies qui échoue silencieusement dans WKWebView, et un entitlement RevenueCat qui entre en conflit avec l'abonnement Stripe de la base web. La réparation est architecturale — et c'est deux fois la même : un modèle d'identité, un magasin d'entitlements.

Une instance Better Auth, trois transports de session

supastack garde une seule configuration Better Auth dans @supastack/auth avec des points d'entrée par surface. Les deux apps web (Next.js 16 et TanStack Start) utilisent des sessions par cookies HttpOnly SameSite=Lax — sûres contre le CSRF par défaut et compatibles Server Components. L'app Expo échange la fin du flux OAuth ou magic link au terme du callback deep link contre un bearer token, le persiste dans expo-secure-store (iOS Keychain / Android Keystore) et l'envoie en en-tête Authorization, validé par le même middleware d'auth.

Le shell desktop Tauri est une webview unique pointant sur l'app web : il hérite directement de la session web — pas de troisième flux d'auth à maintenir. Le guide auth mobile et le guide deep links documentent le contrat de callback ; notre guide monorepo web + mobile montre le code client partagé.

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

Huit passerelles de paiement, un contrat

Chaque prestataire de paiement web — Stripe, Lemon Squeezy, Polar, Creem, Dodo, Paddle, Whop et PayPal — se branche sur le même contrat @supastack/billing, et chaque webhook signé atterrit d'abord dans un ledger webhook_event idempotent avant de pouvoir toucher aux entitlements. Les retries des prestataires et les livraisons désordonnées deviennent des no-ops inoffensifs à la frontière de la base, pas des tickets support.

Les achats intégrés mobiles rejoignent le même ledger via RevenueCat : les reçus de store sont vérifiés côté serveur et les entitlements écrits sur le workspace, pas sur l'appareil — celui qui paie sur iOS est payé immédiatement aussi sur web et desktop. Le guide RevenueCat couvre le câblage App Store / Play ; les webhooks de facturation idempotents expliquent pourquoi le ledger est la pièce porteuse.

Le modèle d'entitlements qui rend la synchronisation ennuyeuse

Pourquoi ça reste ennuyeux : les entitlements vivent sur le workspace et sont résolus côté serveur. Aucun client ne détient l'état « payé » — le web interroge la session, le mobile interroge l'API, le desktop interroge l'app web — et les trois obtiennent la même réponse parce qu'il n'y a qu'un enregistrement pour répondre.

Restauration d'achat sur un nouveau téléphone, renouvellement Stripe sur le web, siège Agency ajouté dans le dashboard — chacun est une écriture dans les mêmes lignes d'entitlements que chaque surface lit à la prochaine demande. Il n'y a pas de moteur de synchro à construire parce qu'il n'y a rien à synchroniser.

PlateformeTransport de sessionChemin de paiementEntitlements lus depuis
Next.js 16 webCookie HttpOnlyN'importe laquelle des 8 passerelles → ledger webhooksLignes d'entitlements Postgres partagées
TanStack Start webCookie HttpOnlyMêmes adaptateurs, même ledgerLignes d'entitlements Postgres partagées
Expo iOS / AndroidBearer token dans expo-secure-storeRevenueCat IAP → reçu vérifié serveurMêmes lignes (via API typée)
Tauri 2 desktopSession web dans la webviewCheckout web dans le shellMêmes lignes (via app web)
Extension MV3Clé API workspace— (lit les données workspace)Mêmes lignes (via /api/v1)

Ce que vous n'avez plus à construire

Converti en soirées de travail, c'est l'écart entre fondation et liste de features : le retour d'auth par deep link, la persistance de token dans SecureStore, huit intégrations de webhooks replay-safe, la vérification des reçus App Store et un modèle d'entitlements qui ne se contredit jamais entre appareils. Le tout livré, testé (693+ tests sans identifiants) et documenté.

Le Full Bundle à $299 contient toutes les surfaces dans un seul dépôt — sièges et palier agence sur la page tarifaire.

FAQ : partager auth et paiements entre plateformes

Les questions que posent les équipes avant de s'engager sur le stack unifié :

  • Les utilisateurs mobile se connectent-ils séparément du web ?, Non. Le flux OAuth ou magic link revient dans l'app par deep link et émet la même session ; l'émetteur est la même instance Better Auth, donc web et mobile répondent pareil à « qui êtes-vous ».
  • Et quelqu'un qui paie sur iOS mais utilise l'app web ?, RevenueCat livre l'achat côté serveur ; l'entitlement est écrit dans les mêmes lignes workspace que le web lit, et l'app web affiche « payé » à la requête suivante.
  • Peut-on commencer web-only et ajouter les apps plus tard ?, Oui — l'auth et la facturation vivent dans les packages partagés, donc les apps mobile et desktop les héritent dès que ces surfaces sont activées.
  • L'app Tauri a-t-elle besoin de son propre checkout ?, Non — le shell desktop réutilise la session et le checkout de l'app web dans sa webview ; il n'y a pas de seconde surface de paiement à sécuriser.

Votre prochain produit commence ici.

Payez une fois. Créez des produits rentables.