Mailmus
Auth

Vérifier les sessions dans votre backend

JWT à courte durée de vie signés EdDSA — vérification locale (JWKS) ou introspection serveur, deux approches avec des compromis différents.

Le SDK navigateur/mobile authentifie vos utilisateurs finaux directement contre Mailmus. Votre propre backend (Express, NestJS, Fastify...) reçoit ensuite l'accessToken sur chaque requête (Authorization: Bearer ...) et doit le vérifier — deux façons de faire, avec un vrai compromis entre les deux.

Ce que contient le token

L'access token est un JWT signé EdDSA (Ed25519, une paire de clés par App), à courte durée de vie (accessTokenTtlSeconds, 900s/15min par défaut — configurable dans Auth → Réglages).

ClaimTypePrésence
substringToujours — l'id de l'EndUser
appIdstringToujours
sidstringToujours — l'id de la session, pour révocation ciblée
rolesstring[]Toujours
orgId, orgRolestringSeulement si une organisation est active sur cette session (voir Organizations)
iat, expnumberToujours (timestamps Unix standard)

Option 1 — Vérification locale (JWKS)

Recommandée par défaut : aucun appel réseau, donc aucune latence ajoutée à vos requêtes.

npm install jose
import { createRemoteJWKSet, jwtVerify } from "jose";

const JWKS = createRemoteJWKSet(
  new URL(`https://api.mailmus.app/apps/${appId}/.well-known/jwks.json`),
);

const { payload } = await jwtVerify(accessToken, JWKS);
// payload.sub = endUserId, payload.appId, payload.sid, payload.roles, ...

createRemoteJWKSet met les clés en cache automatiquement — aucun appel réseau après le premier token vérifié (sauf rotation de clé, gérée par le kid dans l'en-tête du JWT).

Exemple — Guard NestJS

import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from "@nestjs/common";
import { createRemoteJWKSet, jwtVerify } from "jose";

const APP_ID = process.env.MAILMUS_APP_ID!;
const JWKS = createRemoteJWKSet(
  new URL(`https://api.mailmus.app/apps/${APP_ID}/.well-known/jwks.json`),
);

@Injectable()
export class MailmusAuthGuard implements CanActivate {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    const token = request.headers.authorization?.replace("Bearer ", "");
    if (!token) throw new UnauthorizedException();

    try {
      const { payload } = await jwtVerify(token, JWKS);
      request.endUser = { id: payload.sub, roles: payload.roles };
      return true;
    } catch {
      throw new UnauthorizedException("Jeton invalide ou expiré");
    }
  }
}

Limite à connaître : une vérification locale ne sait pas qu'un utilisateur vient d'être banni ou qu'une session a été révoquée (auth.sessions.revoke(), bannissement, reset password) — le token reste valide jusqu'à son expiration naturelle (15 minutes par défaut). Pour la plupart des routes, c'est un compromis acceptable. Pour une action sensible où une révocation doit couper l'accès immédiatement, utilisez l'option 2.

Option 2 — Introspection serveur

Un appel réseau à Mailmus par requête, mais qui reflète l'état réel à l'instant présent : révocation de session, bannissement, tout est vérifié côté Mailmus avant de répondre.

import { SDK } from "mailmus";

const mailmus = new SDK({ bearer: process.env.MAILMUS_SECRET_KEY });

const endUser = await mailmus.endUserVerification.endUserVerifyVerify({
  appId: "app_xxx",
  body: { accessToken },
});
// { id, email, metadata, sessionId, organizationId, organizationRole }

Utilise votre clé secrète (jamais la publiable) — à n'appeler que depuis votre backend, jamais depuis un client.

Laquelle choisir ?

  • Par défaut : vérification locale (JWKS) — rapide, pas de dépendance réseau à la disponibilité de Mailmus pour chaque requête.
  • Pour une action irréversible ou sensible (paiement, suppression de compte, accès à des données critiques) juste après un bannissement/une révocation possible : introspection serveur, pour ne pas laisser une fenêtre de 15 minutes où un token révoqué reste utilisable.

Rien n'empêche de combiner les deux : JWKS locale pour la majorité des routes, introspection ciblée sur les endpoints les plus sensibles.

Suivant

On this page