Authentification & onboarding
Les identifiants vivent dans les variables d’environnement, jamais dans la page. Ce guide couvre la façon dont la console d’essai s’authentifie, et comment tendre un environnement prêt à l’emploi à un coéquipier avec un setup link.
L’environnement d’abord
Un environnement, c’est un nom, une URL de base, des variables et des en-têtes
par défaut ajoutés à chaque requête — plus une couleur d’une palette fermée,
affichée sur le sélecteur : la production en rouge se voit avant l’envoi,
pas après. Le sélecteur porte aussi un badge quand des variables
d’identifiants attendues par le schéma manquent, et au premier chargement
d’un schéma, un bouton propose de créer un environnement par entrée
servers — un amorçage sur demande, jamais automatique. Les environnements
déclarés dans la config sont ajoutés par leur nom au chargement, sans rien
écraser de ce que le lecteur a déjà ; ensuite, c’est son stockage qui fait
foi.
Ce que le schéma déclare, la console le comprend
Chaque scheme de vos securitySchemes obtient un champ qui fonctionne :
bearer, basic, apiKey en en-tête, en paramètre de requête ou en cookie,
OAuth2 et OpenID Connect. La convention tient en une ligne : au scheme X
correspond la variable auth.X. Renseignez-la dans l’environnement actif et
chaque opération protégée par ce scheme l’envoie — laissez-la vide et
l’interpolation {{var}} bloque l’envoi plutôt que de laisser fuir un
{{auth.X}} littéral vers votre API.
Les variables sensibles sont masquées dans l’interface, avec une mise en garde honnête : les valeurs vivent dans le stockage local du navigateur, non chiffrées. Sur une machine partagée, agissez en conséquence.
OAuth2 sans backend
ApiGlow exécute Authorization Code + PKCE entièrement dans le
navigateur : redirection complète vers votre fournisseur d’identité, échange
du code dans la page, jeton dans auth.X — aucun serveur chez nous, jamais
de secret client dans la config. Le flux client credentials est aussi
pris en charge pour les API de machine à machine. Les flux OAuth de la démo
pointent vers un fournisseur simulé ; face à votre API, vous fournissez vos
vraies URL d’autorisation et de jeton.
La seule chose que la config transporte est le client id public, par
scheme — jamais un secret — et le lecteur peut le surcharger avec la
variable auth.X.clientId :
{ "oauth": { "petstore_auth": { "clientId": "public-client-id" } } }Les flows pilotables sont exactement ces deux-là — Authorization Code + PKCE
et client credentials. implicit et password sont documentés depuis le
schéma mais ne portent pas de bouton « Obtenir un jeton ».
Ce qu’un navigateur ne sait pas faire, dit là où ça compte
Deux schemes sont rendus avec leur limite de plateforme énoncée plutôt qu’avec un bouton cassé, à trois endroits chacun — la doc de l’opération, le résumé d’authentification et le bloc credentials de la console :
mutualTLSest documenté mais jamais envoyé : « un navigateur ne peut pas présenter de certificat client — appelez cet endpoint depuis un client qui le peut (cURL, votre propre code) ».- Le flow OAuth2 device authorization (OpenAPI 3.2) n’est pas exécuté : « il interroge le endpoint de jeton hors du navigateur — obtenez le jeton ailleurs et collez-le dans la variable ».
Les deux limites sont celles de la plateforme, pas du schéma : la documentation reste complète, la console refuse simplement de faire semblant.
Quand la page hôte a déjà une session
La page de doc est statique — aucun serveur ne la rend, donc rien ne peut y injecter un jeton par lecteur à la livraison. Mais le lecteur a souvent déjà une session (cookie, SSO) dans ce navigateur, et votre backend saurait lui frapper un jeton d’API à la demande. Le pont d’identifiants hôte ferme cet écart : la page qui embarque ApiGlow enregistre un provider, et l’app le sollicite quand elle a besoin d’identifiants.
<!-- après la balise script d'ApiGlow -->
<script type="module">
apidoc.registerCredentialsProvider(async ({ specId, reason }) => {
const r = await fetch('/api/docs-token', { credentials: 'include' })
if (!r.ok) return null
return { bearerAuth: (await r.json()).access_token }
})
</script>La table retournée est indexée par les noms de schemes de vos
securitySchemes : une chaîne remplit auth.X, un objet remplit les
suffixes façon auth.X.username. Le lecteur arrive sur une doc dont le
badge d’identifiants dit déjà « fournis par l’hôte » — rien à coller,
rien à configurer.
Quatre règles rendent le raisonnement sûr :
- Il ne remplit que le vide. Une valeur de l’hôte ne s’applique que là où l’environnement sélectionné est vide ; une valeur tapée par le lecteur (ou écrite par un flux OAuth) gagne toujours, et l’effacer retombe sur la valeur de l’hôte.
- Mémoire seulement, toujours. Les valeurs de l’hôte ne sont jamais persistées — ni dans le stockage, ni dans les exports d’historique (elles sont capturées comme sensibles, le caviardage s’applique), ni dans les exports d’environnements. Rechargez la page : le provider est simplement redemandé.
- Un seul rejeu sur 401. Si une requête dont les identifiants venaient
de l’hôte prend un 401, l’app redemande une fois le provider
(
reason: "expired") et rejoue une fois — avec une note visible dans le panneau de réponse, jamais une boucle silencieuse. - La frontière de confiance, c’est la page. Seul le code de la page hôte peut enregistrer un provider ; rien dans un document OpenAPI ne peut en déclencher ou en influencer un, et l’app elle-même ne télécharge jamais d’URL d’identifiants.
Deux membres de plus couvrent les cas simples — apidoc.setCredentials(map)
pousse des valeurs que l’hôte détient déjà, apidoc.clearCredentials()
vide le pont à la déconnexion — et un script classique susceptible de
tourner avant l’app écoute l’événement apidoc:ready au lieu de supposer
la globale. En multi-spec, un seul provider sert
toutes les specs : il reçoit le specId actif et route en interne.
Il n’y a délibérément aucune clé de config pour tout cela : le pont
est une surface d’exécution, pour qu’un jeton ne puisse jamais finir écrit
dans une page publique. Le fetch du provider s’authentifie typiquement par
le cookie de session — credentials: "include" et les contraintes
CORS qui l’accompagnent sont à votre charge, comme pour
tout appel authentifié par cookie.
Accueillir un coéquipier : le setup link
Le gestionnaire d’environnements porte une bande à lui — Préparer un coéquipier — avec deux portes d’entrée. La première partage l’environnement que vous avez : vous choisissez ce qui voyage, les variables cochées emportent leur valeur, les autres voyagent par leur nom, avec une valeur vide — un squelette que votre coéquipier remplit avec ses propres identifiants. Les lignes non sensibles partent cochées, les sensibles décochées.
Si vous embarquez un identifiant, la boîte de partage le dit sans détour, en place plutôt que derrière une confirmation : qui détient le lien détient l’identifiant, et un lien survit à la conversation qui l’a porté. Les liens très longs ont aussi leur avertissement, au-delà de 2 000 caractères — certaines messageries tronquent sans prévenir, et c’est le pire sort qui puisse arriver à un lien.
Le fabriquer sans créer l’environnement
Partager part d’un environnement que vous possédez déjà — donc de le créer d’abord chez vous, avec des valeurs que vous ne souhaitez pas forcément garder sur votre machine. La seconde porte de cette bande, Partir de zéro, lève cette contrainte : un formulaire qui décrit l’environnement que l’équipe devrait avoir, et qui en produit le lien. Il est aussi proposé comme carte sur la vue d’accueil, là où un lead atterrit vraiment.
Ce formulaire est un générateur pur : il n’écrit jamais rien. Fabriquer un lien n’est pas créer un environnement ; la boîte n’a aucun chemin vers votre stockage. Vous remplissez un nom, une URL de base, une couleur, des lignes de variables et des lignes d’en-têtes par défaut — chaque variable portant un marqueur sensible et une case embarquer la valeur, décochée par défaut pour les lignes sensibles : un identifiant ne voyage que si vous le dites.
Le lien se reconstruit à la frappe, et les bornes sont vérifiées en direct — celle qui casse est nommée, plutôt que de vous laisser partir avec un lien que le destinataire refuserait. Prévisualiser en destinataire ferme le constructeur et ouvre le lien sur-le-champ : pas une reproduction de la boîte d’arrivée, la boîte d’arrivée elle-même, pour que l’aperçu ne puisse pas diverger de ce que verra votre coéquipier. Annuler n’écrit rien ; Appliquer applique pour de bon, et le bouton le dit. En multi-spec, le lien vise la spec où vous êtes.
Voici la même idée, jouée sur cette page plutôt que dans l’application — un vrai setup link, du format exact qu’ApiGlow sait lire, pointé sur la démo :
FABRIQUER UN SETUP LINK · ESSAI SUR LA DÉMO
Case décochée : auth.api_key voyage par son nom, valeur vide — le squelette que le destinataire remplit.
Ce lien porte maintenant un identifiant : qui détient le lien détient l'identifiant.
Ouvrez le lien : vous voilà à la place du destinataire, et rien n’est écrit
tant que vous n’acceptez pas. Le lien ouvre un tableau de relecture — chaque variable marquée créée, mise
à jour ou conservée, valeurs sensibles cachées, valeurs vides signalées
« à remplir » — et le lien est aussitôt retiré de la barre d’adresse. Trois
garde-fous refusent les situations douteuses : un lien illisible ne change
rien, un lien construit pour une autre spec ne change rien, et sur une
installation environmentsLocked, un setup link ne peut rien changer du
tout.
Générer des liens depuis un script
Ni l’un ni l’autre formulaire n’a quoi que ce soit de magique, et aucun n’est
nécessaire pour produire un lien : c’est l’URL de votre doc suivie d’un
pseudo-paramètre setup dans le hash, portant un JSON encodé en
base64url. C’est ce qui met les liens d’accueil à la portée d’un job de CI ou
de la page d’intranet de l’équipe :
https://docs.example.com/#/?setup=<base64url(payload)>Le payload, version 1 :
{
"v": 1,
"spec": "petstore",
"env": {
"name": "Staging",
"baseUrl": "https://staging.petstore.example",
"vars": [
["auth.api_key", "", true],
["team", "docs-squad"]
],
"headers": [["X-Team", "docs"]]
}
}Ce qu’il faut savoir pour l’écrire soi-même :
- Chaque variable est une ligne
[nom, valeur]ou[nom, valeur, true]— le troisième élément marque la variable sensible (le champ du destinataire naît masqué). Le drapeau voyage même quand la valeur ne voyage pas. - Une valeur vide est le squelette : la variable est créée par son nom, le destinataire la remplit.
specest optionnel mais recommandé sur une installation multi-spec : sans lui, pas de garde-fou « mauvaise API ».baseUrl,coloretheaderssont optionnels.- L’encodage est du base64url sans padding (
+→-,/→_,=retirés). En Node :Buffer.from(JSON.stringify(payload)).toString("base64url"). - Bornes appliquées à la lecture : 8 Ko de JSON décodé, 50 variables, 20 en-têtes, 200 caractères par nom, 4 Ko par valeur — au-delà de l’une d’elles le lien entier est refusé comme illisible, et un nom employé deux fois le refuse aussi. Et au-delà de ~2 000 caractères d’URL, méfiez-vous des messageries qui tronquent.
Le premier appel, généré
features: { "onboarding": true } ajoute une page « Premier appel » en
tête de la nav de référence (#/first-call), pour le lecteur qui n’a
encore rien envoyé : ApiGlow choisit la lecture la plus simple que le
schéma déclare — un GET, sans corps, plus rien à taper une fois les
exemples déclarés pré-remplis — et la présente sous un préambule en trois
pas : choisir un langage, renseigner les identifiants, appuyer sur
Envoyer. Les trois pas se jouent dans la vraie console d’essai : le
lecteur finit exactement là où il travaillera. Désactivée par défaut, et
absente de toute façon quand le schéma ne déclare aucune lecture de ce
genre.
Déploiements verrouillés
environmentsLocked s’adresse aux installations d’entreprise encadrées :
les environnements viennent de la configuration du site et les lecteurs ne
peuvent pas les modifier — ce qui neutralise aussi les setup links entrants.
Voir la référence de configuration pour la clé,
et Console d’essai & CORS pour comprendre pourquoi un
appel correctement authentifié peut malgré tout être bloqué par le
navigateur.