← All posts

Nous nous connectons à notre propre console admin avec notre propre SAML. Voici ce que cela a attrapé.

Authagonal·June 22, 2026
samlssodogfoodingengineering

Il existe une version du dogfooding qui n'est qu'un slogan, et une version où vos propres employés ne peuvent pas livrer de code tant que le bug n'est pas corrigé. Nous pratiquons la seconde. La console du personnel Authagonal, celle dont nous nous servons pour gérer chaque tenant, s'authentifie via Authagonal lui-même : SAML single sign-on depuis notre annuaire Entra, avec SCIM qui décide qui entre et ce qu'il a le droit de faire. Il n'y a pas de table séparée pour les mots de passe admin. Nous l'avons supprimée. Si notre propre SAML est cassé, nous sommes verrouillés hors de notre propre produit.

C'est inconfortable, et précisément de la manière utile. Cela transforme "le SSO est une fonctionnalité enterprise que nous prenons en charge" en "le SSO est la seule façon dont les gens qui ont construit ça peuvent travailler aujourd'hui." Voici ce que le fait d'être notre propre client a permis d'attraper.

Un build trimmé qui cassait la vérification de signature

Nous publions le serveur d'auth en version trimmée, pour garder l'image petite. Le trimming supprime agressivement le code dont il ne peut pas prouver l'utilisation, et la réflexion lui cache cette utilisation. .NET résout ses algorithmes cryptographiques de signature XML par nom, par réflexion, via CryptoConfig. Le trimmer ne pouvait pas voir que ces types étaient nécessaires, les a supprimés, et SignedXml s'est discrètement retrouvé incapable de construire l'algorithme. La vérification de signature SAML, l'étape qui prouve que la connexion est réelle, a levé une référence nulle à l'exécution.

Les tests unitaires passaient, parce qu'ils s'exécutaient contre le build non trimmé où les types existaient encore. Seul l'artefact de production trimmé échouait, et il échouait exactement au moment où un humain tentait de se connecter. Nous livrons désormais le serveur d'auth non trimmé, avec une saine méfiance envers le trimming de tout ce qui touche à la cryptographie basée sur la réflexion. Si nous nous contentions de prendre en charge SAML au lieu d'en vivre, ce serait le rapport d'incident d'un client plutôt que le nôtre.

Le provisioning est le véritable login

Authentifier un utilisateur, c'est la moitié facile du SSO. La moitié difficile, c'est de décider ce qu'il a le droit de faire et de garder cela synchronisé à mesure que les gens arrivent et partent. Nous pilotons cela avec SCIM : l'appartenance aux groupes Entra est mappée vers des rôles, résolue au moment précis où un token est émis, et non copiée une fois pour toutes à la création du compte. Ajoutez quelqu'un au bon groupe et il a accès dès sa prochaine connexion ; retirez-le et l'accès disparaît. Notre propre liste d'accès fait du dogfooding avec exactement le mapping groupe-vers-rôle que nous livrons.

Ce câblage fait remonter une catégorie de bug qui n'existe que lorsque l'authentification et l'autorisation vivent dans deux systèmes différents : un admin tout juste provisionné pouvait s'authentifier avant que son rôle soit complètement arrivé, laissant la première connexion dans un état valide mais non autorisé. Le correctif est dans l'ordre du provisioning, pas dans le login, et on ne le trouve qu'en étant le nouvel admin qui se connecte pour la première fois.

Un 500 qui aurait dû être un 403

Le plus petit bug était le plus gênant. Quand un utilisateur authentifié atteignait quelque chose qu'il n'avait pas le droit de faire, l'API renvoyait un 500 au lieu d'un 403 propre, parce que le chemin de code qui émet la réponse "interdit" dépendait d'un service qui n'était pas câblé dans cet hôte. Une requête refusée est censée être un résultat calme et attendu, pas une erreur serveur. Invisible jusqu'à ce que ce soit vous qui vous fassiez refuser.

La frontière qui nous tient le plus à cœur

Sous tout cela se trouve la seule règle qu'une plateforme d'identité multi-tenant ne peut pas se permettre de rater : un tenant ne doit jamais devenir notre admin. Nous ne faisons pas confiance à une seule vérification. La plateforme est son propre issuer et un tenant ne peut pas revendiquer son slug ; la clé de signature de la plateforme est distincte de celle de chaque tenant, si bien qu'un token signé pour un tenant ne peut pas être rejoué comme un token de plateforme ; et le store de la plateforme impose les rôles de plateforme de façon indépendante. Trois verrous, parce que le coût d'un seul qui s'ouvre par défaut, c'est le produit tout entier.

Le point essentiel

Aucun de ces bugs n'a été attrapé par un test astucieux. Ils ont été attrapés par une personne essayant de faire son travail et n'y parvenant pas. Voilà l'argument pour utiliser son propre produit à la profondeur où il peut vous faire mal : cela convertit les bugs cachés dans les interstices entre les systèmes en bugs que vous corrigez avant le petit-déjeuner, parce que vous ne pouvez pas livrer tant que ce n'est pas fait.

Tout ce sur quoi repose notre console (SSO, SAML, SCIM, MFA, journaux d'audit) est inclus dans chaque formule Authagonal, ni verrouillé derrière un palier ni facturé par connexion. Voyez ce qui est inclus.