Un compte pour toute la suite : comment comet fait du SSO
Zitadel, OIDC avec PKCE, session SSO partagée, JWT validés hors ligne par JWKS, droits portés par le jeton : comment comet fait tenir 16 applications derrière une seule identité.
16 juin 2026 · 5 min de lecture
Seize applications, cela pourrait vouloir dire seize comptes, seize mots de passe, seize écrans de connexion légèrement différents — et, côté administration, seize annuaires à maintenir. C'est exactement ce que comet refuse. Dans la suite, il y a une identité par personne, un seul écran de connexion, et une session qui vaut partout : se connecter à une application vous connecte à toutes. Voici comment c'est construit, et quels compromis nous avons choisis.
Un IAM central plutôt que seize annuaires
Toute l'identité de la suite repose sur un IAM (Identity and Access Management) centralisé : Zitadel, que nous déployons avec le reste de l'infrastructure de la suite. C'est lui — et lui seul — qui connaît les mots de passe, applique les politiques de sécurité et émet les jetons.
Le corollaire est important : aucune application de la suite ne voit jamais un mot de passe. Le mail, l'agenda, le stockage de fichiers ne stockent aucun secret d'authentification. Une application compromise ne peut pas fuiter ce qu'elle n'a jamais eu.
OIDC Authorization Code + PKCE pour chaque application
Chaque frontend de la suite est un client OpenID Connect déclaré auprès de Zitadel, et utilise le flux Authorization Code avec PKCE. Concrètement, quand vous ouvrez une application sans être connecté :
1. L'app génère un code_verifier aléatoire
et son empreinte, le code_challenge.
2. Redirection vers l'IAM :
GET /oauth/v2/authorize
?client_id=<app>
&response_type=code
&code_challenge=<empreinte>
&code_challenge_method=S256
&redirect_uri=<app>/auth/callback
3. Authentification sur l'écran de connexion de la suite.
4. Retour vers l'app avec un code à usage unique.
5. L'app échange code + code_verifier contre les jetons.
Pourquoi PKCE ? Parce que nos frontends sont des applications web côté navigateur : des clients « publics », incapables de garder un secret client. PKCE compense en liant cryptographiquement le code d'autorisation au navigateur qui a initié le flux — un code intercepté est inutilisable sans le code_verifier d'origine, qui ne circule jamais.
Un écran de connexion unique, une session partagée
L'étape 3 mérite qu'on s'y arrête. Toutes les applications redirigent vers le même écran de connexion, celui de la suite — même charte, même comportement, quel que soit le point d'entrée. C'est là que vivent le mot de passe oublié, l'inscription, les codes de vérification.
Surtout, cet écran matérialise la session SSO : une fois authentifié pour une application, la session est partagée. Ouvrez une deuxième application, le flux OIDC se déroule intégralement — mais silencieusement : l'IAM reconnaît la session existante et renvoie immédiatement un code, sans rien vous demander. L'expérience vécue est simple : on se connecte une fois le matin, la suite entière est ouverte. Et la déconnexion est symétrique : elle détruit la session centrale, donc ferme toutes les applications d'un geste.
Des JWT validés hors ligne, par JWKS
Côté backends, chaque requête API porte un jeton d'accès au format JWT, signé par l'IAM. Le point d'architecture décisif : les backends valident ces jetons hors ligne. Zitadel publie ses clés publiques à une adresse standard (le JWKS, JSON Web Key Set) ; chaque backend les récupère, les met en cache, et vérifie ensuite localement la signature et les claims de chaque jeton :
GET <issuer>/oauth/v2/keys ← récupéré et mis en cache
Pour chaque requête entrante :
vérifier la signature (clé publique)
vérifier iss (émetteur attendu)
vérifier aud (ce jeton vise-t-il la suite ?)
vérifier exp (jeton non expiré)
Aucun appel réseau vers l'IAM sur le chemin critique. Les bénéfices sont directs : pas de latence ajoutée à chaque requête, et pas de point de défaillance unique — si l'IAM redémarre, les utilisateurs déjà munis de jetons valides continuent de travailler. La vérification d'audience ajoute un garde-fou : un jeton émis pour la suite fonctionne sur les backends de la suite, un jeton émis pour un autre client est refusé.
Les droits d'accès voyagent dans le jeton
L'authentification dit qui vous êtes ; il reste à dire ce à quoi vous avez droit. Dans comet, l'accès à chaque application est porté par des rôles — un rôle app:mail, un rôle app:drive, et ainsi de suite — attribués dans l'IAM et « assertés » directement dans le jeton d'accès, sous forme de claim :
{
"iss": "https://auth.exemple.interne",
"sub": "u-102394…",
"exp": 1766050000,
"urn:zitadel:iam:org:project:roles": {
"app:mail": { … },
"app:drive": { … },
"app:docs": { … }
}
}
Chaque backend n'a alors qu'à lire le claim : le rôle de son application est présent, la requête passe ; absent, elle est refusée avec une erreur explicite. Côté interface, le même mécanisme filtre le lanceur d'applications — vous ne voyez que les applications auxquelles vous avez droit. Et c'est administrable centralement : retirer une application à quelqu'un est une opération dans l'IAM, pas seize.
Révocation : à l'échéance du jeton — et on l'assume
La validation hors ligne a un coût, qu'il faut nommer : un jeton déjà émis reste valide jusqu'à son expiration. Retirez un droit à quelqu'un, et son backend continuera d'accepter son jeton courant jusqu'au prochain rafraîchissement — c'est à ce moment que le nouveau jeton, émis sans le rôle retiré, prend effet.
C'est un compromis classique, et nous le faisons les yeux ouverts : des jetons à durée de vie courte bornent la fenêtre à quelques minutes, l'interface réagit immédiatement, et en échange nous gagnons des backends rapides et résilients qui ne dépendent pas de l'IAM à chaque requête. Une révocation strictement instantanée exigerait de réintroduire un appel centralisé sur le chemin de chaque requête — précisément ce que cette architecture évite.
Ce que vous y gagnez
Résumons ce que cette tuyauterie produit, vue de l'utilisateur et de l'administrateur.
- Une identité, pas seize. Un seul mot de passe à retenir — et donc un mot de passe qui peut être fort.
- Zéro secret dans les applications. La surface d'attaque de l'authentification se concentre en un point, durci et supervisé.
- Une administration centrale. Créer un compte, couper un accès, désactiver une personne qui quitte l'organisation : une opération, effective partout.
- Des standards, pas de magie. OIDC, PKCE, JWT, JWKS : tout repose sur des protocoles ouverts et documentés. Rien dans cette architecture ne vous enferme — c'est aussi cela, la souveraineté.
Poursuivre la lecture
Ingénierie
Mesurer le stockage sans lire vos fichiers
Deltas d'octets idempotents, réconciliation périodique, quota en trois temps et refus structuré : comment comet mesure votre stockage sans jamais lire vos fichiers.
Produit
Orgs, équipes, sièges : le modèle Workspace de comet
Org personnelle pour chacun, organisations gratuites, sièges réellement appliqués, équipes qui pilotent l'accès aux apps et provisioning automatique : le modèle Workspace de comet.