TypeScript — Browser
SDK navigateur @mailmus/auth — sign-up/sign-in de vos utilisateurs finaux, clé publishable.
Package : @mailmus/auth — écrit à la main (pas généré), zéro dépendance runtime, ESM uniquement. Authentifié avec votre clé publishable : jamais de risque à l'exposer côté navigateur, contrairement à la clé secrète.
npm install @mailmus/authimport { MailmusAuthClient } from "@mailmus/auth";
const auth = new MailmusAuthClient({
appId: "app_xxx",
publishableKey: "pk_xxx",
serverURL: "https://api.mailmus.app",
hostedPagesURL: "https://www.mailmus.app",
});serverURL et hostedPagesURL sont obligatoires — ce SDK n'embarque aucune valeur par défaut de production, ces deux valeurs sont propres à votre environnement.
Aucun cookie n'est utilisé : les tokens sont transportés en Bearer et persistés côté client (localStorage par défaut, TokenStorage pluggable via l'option storage).
Sign-up / Sign-in
await auth.signUp({ email, password });
await auth.signIn({ email, password }); // peut renvoyer un défi MFA, voir isMfaChallenge
await auth.signOut();
await auth.requestMagicLink({ email, redirectUri });
await auth.verifyMagicLink({ token });
await auth.requestOtp({ email });
await auth.verifyOtp({ email, code });
await auth.forgotPassword({ email, redirectUri });
await auth.resetPassword({ token, newPassword });
await auth.verifyEmail({ token });Toute méthode de première connexion (signIn, verifyMagicLink, verifyOtp, resetPassword) peut renvoyer un défi MFA au lieu d'une session — utilisez isMfaChallenge(result) pour le détecter.
auth.oauth — OAuth Google / GitHub / Apple
// Redirection pleine page
await auth.oauth.redirect({ provider: "google", redirectUri });
// Ou popup, résout directement avec les tokens
const tokens = await auth.oauth.popup({ provider: "google", redirectUri });Le SDK ne parle jamais directement aux providers OAuth — tout transite par les pages hébergées Mailmus. redirectUri doit figurer dans l'allowlist de redirection de l'App (App → Auth Settings).
auth.mfa — Double authentification (TOTP)
const { secret, otpauthUrl } = await auth.mfa.enroll();
const { backupCodes } = await auth.mfa.confirm({ code }); // code du 1er TOTP généré
await auth.mfa.disable({ code });
// Continuation d'un sign-in ayant renvoyé isMfaChallenge(result) === true
const { endUser } = await auth.mfa.verify({ challengeToken, code });auth.sessions — Appareils connectés
const sessions = await auth.sessions.list(); // { current: boolean } par entrée
await auth.sessions.revoke(sessionId);auth.organizations — Organizations (B2B, self-service)
const orgs = await auth.organizations.mine();
await auth.organizations.setActive(organizationId); // force un refresh interne
await auth.organizations.clearActive();
await auth.organizations.leave(organizationId);
await auth.organizations.acceptInvitation(token);
await auth.organizations.previewInvitation(token); // ne nécessite pas de sessionauth.sso — SSO/SAML (Home Realm Discovery)
const result = await auth.sso.start({ email, redirectUri });
// Si ssoRequired, la méthode navigue déjà vers l'IdP — rien à faire de plus.État de session
auth.session.getState(); // { status: "signed-out" } | { status: "signed-in", endUser, organizationId }
const unsubscribe = auth.session.subscribe((state) => { /* ... */ });Pour tout ce qui touche à l'administration (lister/bannir des utilisateurs, gérer des Organizations depuis votre backend...), voir le SDK serveur.