Un point de terminaison d'activation de licence sur l'un de mes projets Laravel a commencé à rejeter chaque jeton. Pas certains jetons. Chaque jeton, y compris celui que le même serveur avait émis, avait quatre-vingt-dix secondes plus tôt. Les journaux ont dit token expired. Les jetons n'étaient pas expirés. J'ai passé la majeure partie d'un samedi convaincu que l'horloge de la boîte avait dérivé.
Il n'avait pas. Le bug était une ligne :
if (payload.exp < Date.now()) throw new Error('token expired')
exp Dans un JWT est instant Depuis l'époque — RFC 7519 §4.1.4, cela n'est pas ambigu. Date.now() En JavaScript, les retours millisecondes. Je comparais donc un nombre à dix chiffres à un nombre à treize chiffres, et les nombres à dix chiffres sont toujours plus petits. Chaque jeton de l'univers était expiré, pour toujours. Le correctif était Date.now() / 1000. Le diagnostic a pris huit heures parce que je n'ai jamais regardé Au jeton - j'ai continué à relire mon propre code, ce qui équivaut à déboguer la recherche de vos lunettes tout en les portant.
Ce qui a finalement brisé la boucle, c'est de coller le jeton dans un décodeur, de lire exp: 1748952000, convertir cela en date et voir un horodatage dans deux semaines. Le jeton était bien. Ma comparaison était erronée. Trente secondes de regarder les données ont battu huit heures de visionnage du code.
C'est de cela qu'il s'agit de ce guide. Pas de philosophie intelligente de débogage - les outils de navigateur spécifiques, ennuyeux et peu glamour que je garde dans un groupe d'onglets appelé "Debug API", à quoi sert chacun et les modes de défaillance qu'ils attrapent. Tout ici fonctionne côté client sur toolz.dev, ce qui compte plus que ce qui semble le faire lorsque la chose que vous êtes sur le point de coller est un jeton de production.
tl;dr : Lorsqu'une API se comporte mal, arrêtez de lire votre code et commencez à lire la charge utile. Formatez la réponse avec le Formateur JSON. Craquez le jeton avec le Décodeur JWT, pas un outil générique de base64. virer
exp,iat, etX-RateLimit-Reseten dates réelles avec le Convertisseur d'horodatage. Comparez une réponse de travail à une réponse cassée avec le Diff de texte Ou, mieux, le Diff JSON. Décoder la chaîne de requêtes avec la Encodeur d'URL. Tout cela s'exécute dans votre navigateur - le jeton ne passe jamais sur le fil.
Pourquoi le débogage d'une API semble-t-il tellement pire que le code de débogage ?
Parce que vous ne pouvez pas vous en sortir. Un bogue local a une trace de pile, un débogueur et un point d'arrêt. Un bogue d'API a une chaîne. Le serveur de quelqu'un d'autre a produit cette chaîne, selon des règles que vous ne connaissez qu'à moitié, et votre travail consiste à travailler en arrière.
Cela inverse la compétence habituelle. Le goulot d'étranglement n'est pas logique, c'est lisibilité. Presque tous les bogues d'API que j'ai poursuivis au cours des dernières années étaient invisibles jusqu'à ce que je rende les données lisibles :
- Une réponse JSON réduite de 4 000 caractères qui s'est avérée avoir
"data": nullEnterré à six. - Une charge utile Base64 qui a décodé un message d'erreur, l'API était trop polie pour être insérée dans le code d'état.
- Un webhook qui a échoué à la vérification de signature parce que le corps avait une nouvelle ligne de suivi, mon client HTTP s'ajoutait utilement.
- Un horodatage qui était en millisecondes lorsque les médecins ont dit seconde. (Deux fois. différentes entreprises.)
Aucun de ces problèmes n'était difficile. Tous étaient illisible problèmes. Les outils ci-dessous existent pour rendre les données lisibles suffisamment rapidement pour que vous remarquiez la chose que vos yeux glisseraient autrement.
Quel outil pour quel symptôme ?
C'est la table que j'aurais aimé que quelqu'un m'ait remis il y a cinq ans. Symptôme à gauche, premier déplacement à droite.
| Le symptôme | Ce qui est généralement vrai | Premier coup |
|---|---|---|
| La réponse est une ligne géante, ne peut pas voir la structure | Rien n'est cassé, c'est juste minime | Formateur JSON |
401/403 Sur un jeton, vous venez de frapper |
Horloge, réclamation ou bogue de comparaison | Décodeur JWT → vérifier exp, aud, iss |
| La date s'affiche comme 1970 ou l'année 56122 | Désappariement des secondes/millisecondes | Convertisseur d'horodatage |
| "Cela a fonctionné hier" | Un champ a changé de forme | Diff JSON Ancien ou nouveau réponse |
| Les paramètres arrivent mutilés ou tronqués | Double encodage ou un échec &/+ |
Encodeur d'URL |
| La signature du webhook ne correspond jamais | Les octets de corps diffèrent de ce que vous hachage | générateur de hasch Sur le corps brut exact |
Authorization: Basic ... rejeté |
Les informations d'identification sont erronées ou erronées | Convertisseur de base64 |
| Le déploiement par la configuration échoue, l'API ne s'exécute même jamais | IMPRESSION DE YAML | Validateur de YAML |
| Deux réponses semblent identiques mais se comportent différemment | caractère invisible | Diff de texte |
Tout ce qui est ci-dessous est la version longue de ce tableau.
Comment rendre une réponse API lisible en dix secondes ?
Collez-le dans le Formateur JSON. C'est toute la technique, et je ne suis pas désinvolte - la seule habitude de débogage à effet de force le plus élevé que j'ai est de refuser de raisonner Une charge utile que je n'ai pas formatée.
Voici une forme de réponse que j'obtiens d'un fournisseur de facturation, exactement comme elle se détache du fil :
{"subscriptions":[{"id":"sub_7f3d8a2b","status":"active","plan":{"id":"pro_annual","interval":"year","amount":9900},"current_period_end":1748952000,"cancel_at_period_end":false}],"has_more":false}
Formaté, c'est un objet entièrement différent, non pas pour l'analyseur, mais pour moi :
{
"subscriptions": [
{
"id": "sub_7f3d8a2b",
"status": "active",
"plan": {
"id": "pro_annual",
"interval": "year",
"amount": 9900
},
"current_period_end": 1748952000,
"cancel_at_period_end": false
}
],
"has_more": false
}
Maintenant je peux voir ça amount est 9900 et non 99.00 — C'est en centimes, qui est le bogue d'intégration le plus courant dans les paiements — et que current_period_end est un entier à dix chiffres, ce qui signifie quelques secondes, ce qui signifie ne pas le remettre à new Date() directement.
La validation capte ce que vos yeux n'ont pas
Le formatage est également valide. Une erreur d'analyse est une information. Les erreurs qui apparaissent réellement dans les charges utiles réelles :
- virgule de fuite. Légal en Javascript, illégal en JSON (selon RFC 8259). Les luminaires modifiés à la main en sont pleins.
- Devis uniques. JSON nécessite des guillemets doubles.
str(dict)La sortie n'est pas JSON, peu importe à quel point elle y ressemble. - Clés non indiquées. Même histoire - c'est un objet JavaScript littéral, pas JSON.
NaN/Infinity. Certains sérialiseurs les émettent. JSON n'a pas de tels littéraux.- une nomenclature. Un repère de commande octet UTF-8 devant
{Fait qu'un analyseur strict rejettera un document qui semble parfait à l'écran.
Si votre JSON est valide mais que le forme est faux, c'est un outil différent - voir la section diff ci-dessous.
Pourquoi utiliser un décodeur JWT au lieu de simplement décoder le jeton en base64 ?
Vous pouvez base64-décoder un JWT à la main. Je l'ai fait pendant des années. C'est une mauvaise habitude, et voici pourquoi.
Un JWT (RFC 7519) est composé de trois morceaux séparés par des points : en-tête, charge utile, signature. Chaque morceau est Base64url, pas standard Base64 — RFC 4648 §5, l'alphabet URL-safe qui échange +→- et /→_ et laisse généralement tomber le = Rembourrage. Amenez-le à un décodeur Standard-Base64 strict et il vous donnera une erreur ou vous donnera en silence des octets de déchets. Ainsi, la méthode de la main signifie diviser des points, re-padding et échanger l'alphabet, à chaque fois, puis regarder JSON brut.
le Décodeur JWT fait tout cela en une seule pâte et - la partie qui fait réellement gagner du temps - présente les réclamations comme des réclamations. Ceux que je vérifie, dans l'ordre :
exp(expiration) etiat(délivré à) — les deux numériqueDate, c'est-à-dire instant Depuis le 1970-01-01 UTC. C'est le terrain qui a mangé mon samedi.aud(Audience) — Un jeton frappé pour votre API de staging sera structurellement parfait et toujours rejeté par Prod.iss(Emetteur) — Après une migration d'identité, c'est le domaine qui a changé tranquillement.algDans l'en-tête - s'il est indiquénone, vous avez un problème de sécurité, pas un problème de débogage.
Prenez le jeton d'exemple canonique que tout le monde voit :
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
En-tête : {"alg":"HS256","typ":"JWT"}. Charge utile : {"sub":"1234567890","name":"John Doe","iat":1516239022}. et iat il y a 2018-01-18T01:30:22Z — Ce que vous ne savez qu'en l'exécutant via un convertisseur d'horodatage, qui est l'essentiel de la section suivante.
La chose qu'un décodeur ne fait pas
Le décodage ne vérifie pas. Tout le monde peut décoder un JWT, la charge utile est codée et non cryptée. Un décodeur vous indique ce que le jeton prétentions, jamais si la demande est vraie. La vérification de signature se produit sur votre serveur avec votre secret, et aucun outil de navigateur ne devrait jamais être remis ce secret. Traitez un JWT décodé de la façon dont vous traitez une soumission de formulaire : comme une affirmation d'un étranger.
Comment arrêter de me tromper sur les horodatages ?
Apprenez à lire le nombre de chiffres. Il s'agit de la compétence de débogage la moins chère dans tout le domaine et il faut une minute pour apprendre.
| chiffres | unité | exemple | new Date(x) en JS vous donne |
|---|---|---|---|
| 10 | instant | 1748952000 |
1970-01-21 - évidemment faux |
| 13 | millisecondes | 1748952000000 |
la bonne date |
| 16 | microsecondes | 1748952000000000 |
inepties |
Dix chiffres signifient secondes. Treize signifie millisecondes. Date Le constructeur veut des millisecondes, Unix, Python time.time(), va Unix(), php's time(), et la plupart des API' exp Les champs parlent quelques secondes. Tout ce qui est en aval de ce décalage est le chaos.
Et le chaos est bruyant dans un sens et silencieux dans l'autre. alimenter instant à un analyseur milliseconde et vous obtenez 1970 - un bogue si évident que vous le corrigez en une minute. alimenter millisecondes à un instant analyseur et vous obtenez l'année 56122. J'ai vérifié : 1708876200000, interprété comme une seconde, atterrit le 17 février de l'année 56122. C'est la direction qui expédie tranquillement, car rien ne jette - un abonnement n'expire tout simplement jamais et personne ne le remarque pour un quart.
le Convertisseur d'horodatage existe pour que vous puissiez le régler en une seule pâte au lieu de vous argumenter. coller 1748952000, lisez la date, passez à autre chose. Collez le X-RateLimit-Reset En-tête, votre API se plaint et découvrez que vous avez quatre minutes pour attendre, pas quatre heures. Si l'horodatage est naïf (non Z, pas de décalage) et vous devez raisonner sur ce que cela signifie dans une autre région, le Convertisseur de fuseau horaire est le suivi.
Deux autres pièges à horodatage à connaître
Le problème de 2038 est réel et daté. Un compteur de 32 bits de seconde signé déborde à 2147483647, ce qui est 2038-01-19T03:14:07Z. Tout système stockant toujours du temps dans un INT 32 bits signé – et il y en a plus dans les colonnes de base de données intégrées et héritées que quiconque ne le souhaite – se casse alors. Si vous configurez aujourd'hui des expirations à long terme, vous pouvez déjà atteindre ce problème.
Les horodatages naïfs sont un mensonge par omission. 2026-02-25T14:30:00 sans aucune fuite Z et non +05:30 Ce n'est pas un moment, c'est un moment dans un endroit non précisé. Je traite toute API qui renvoie des horodatages naïfs comme un rapport de bogue en attente de dépôt. Préférez la RFC 3339 (2026-02-25T14:30:00Z), qui est le profil strict et sans ambiguïté de l'ISO 8601 que le Web utilise réellement.
Que dois-je faire lorsque "cela a fonctionné hier" ?
Diff le. Ne théorisez pas - diff.
Capturez la réponse de l'environnement de travail (ou déterrez le dernier bon de vos journaux) et la réponse de la cassée, et mettez-les côte à côte. Neuf fois sur dix, il y a exactement une différence et il vous regarde en cinq secondes.
Pour JSON, accédez à la Diff JSON avant le diff de texte. Il analyse les deux côtés et compare structure, ce qui signifie que les clés réorganisées et les différentes empreintes n'apparaissent pas comme des changements - seuls les vrais le font. Un différentiel de texte de deux documents JSON qu'un serveur sérialisé dans un ordre de clé différent s'allumera comme un sapin de Noël et ne vous dira rien.
Pour tout ce qui n'est pas JSON — en-têtes, corps bruts, fichiers de configuration, curl Sortie — Utilisez le Diff de texte. Sa spécialité est la classe de changement que vos yeux sont physiquement incapables de capturer : un espace de fin, un onglet qui est devenu quatre espaces, une ligne CRLF qui se terminait par une machine Windows, un devis bouclé qu'un site de documentation a remplacé un site droit lorsque vous avez copié l'exemple. J'ai écrit un article entier sur Pourquoi les comparaisons de textes occulaires échouent, parce que cela m'a coûté une fois une escalade de support.
Pourquoi mes paramètres de requête continuent-ils d'arriver cassés ?
Parce que l'encodage d'URL a trois ou quatre saveurs subtilement différentes et que la pile de tout le monde en choisit une autre.
Les classiques, dans l'ordre approximatif de la fréquence à laquelle ils m'ont mordu :
+contre%20. Dans une chaîne de requête,+signifie historiquement un espace (leapplication/x-www-form-urlencodedconvention). Dans un segment de chemin,+signifie un plus littéral. Ainsi, une signature Base64 contenant+, déposé dans une chaîne de requête non encodée, arrive avec des espaces et la vérification de signature échoue. C'est vraiment méchant parce que la valeur apparence directement dans les journaux.- Double encodage.
%2Fse transforme%252FParce que deux couches de votre pile l'ont tous deux codée utilement. Le symptôme est un paramètre qui gagne des signes de pourcentage à chaque fois qu'il passe par un proxy. - un brut
&à l'intérieur d'une valeur. Divise votre paramètre en deux. à présentname=Ben & Jerryestname=BenPlus un param mystère appeléJerry.
Collez l'URL dans le Encodeur d'URL et décoder. Si le décodage une fois laisse encore des échappements à pourcentage, vous avez trouvé votre double encodage. C'est tout le diagnostic.
Comment déboguer un webhook qui ne vérifie pas ?
C'est celui qui sépare "Je comprends http" de "J'ai été sur appel".
Presque tous les fournisseurs de webhooks signent la charge utile avec un HMAC et place le résultat dans un en-tête. Votre travail consiste à calculer le même HMAC et à comparer. Quand il ne correspond pas, la signature n'est presque jamais le problème. Les octets sont le problème. Vous ne hachez pas ce qu'ils ont haché.
Les suspects habituels :
- Vous avez haché le corps analysé et re-sérialisé. Votre framework a analysé le JSON dans un objet, vous avez appelé
JSON.stringify()Sur celui-ci, et maintenant l'ordre des clés ou l'espace blanc diffère d'un caractère. Vous devez hacher le âpre Corps de demande, octets tels qu'ils ont été reçus. En express, cela signifie capturer le tampon brut avantexpress.json()y arrive; à Laravel, cela signifie$request->getContent(), pas$request->all(). - Une nouvelle ligne de fuite. Certains clients en joignent un. Le fournisseur ne l'a pas fait.
- Vous hachez la chaîne codée en hexagone au lieu des octets bruts, ou comparant Hex à Base64.
- Carset. Le corps a un caractère multi-octets et quelque chose en cours de route l'a transcodé.
le générateur de hasch C'est comme ça que j'isole ceci : prenez la chaîne de corps exacte, hachez-la, comparez avec ce que mon code a produit pour ce qu'il a produit. idée était le même corps. Si ces deux hachages diffèrent, mon code ne voit pas les octets que je pense qu'il voit, et le problème n'a jamais été cryptographique. (Aussi à savoir : si un fournisseur propose toujours des signatures MD5 ou SHA-1, c'est un signal sur l'âge de sa plate-forme. SHA-256 est le sol maintenant.)
Qu'est-ce qui vit dans le groupe de débogage ?
Le casting de soutien - moins glamour, gagne toujours sa place :
- Générateur UUID — Pour un nettoyage
X-Request-IDÀ chaque appel de test, vous pouvez donc le enregistrer dans trois journaux de services. Il est à sa connaissance que les UUID ont obtenu un rafraîchissement des spécifications : RFC 9562 (2024) RFC 4122 obsolète et standardisé UUIDv7, qui est ordonné dans le temps et donc beaucoup plus gentil avec l'indice B-tree de votre base de données que le V4 aléatoire. Si vous choisissez un schéma d'identification pour une nouvelle table aujourd'hui, c'est celui-là sur lequel lire. Il y a un Décomposition plus longue des versions UUID Si vous le voulez. - Convertisseur de base64 — pour
Authorization: BasicEn-têtes (RFC 7617 : il estbase64(user:password), et oui, c'est l'encodage, pas la sécurité - TLS est ce qui le protège), et pour les blobs binaires en ligne, certains éléments d'API dans les champs JSON. Base64 vous coûte environ 33 % de frais généraux, c'est pourquoi une charge utile "inattendue" contient souvent juste un fichier. le Guide complet de base64 Couvre la distinction Base64url qui fait trébucher les gens. - Validateur de YAML — Parce que la moitié de mes échecs d'API au cours de la dernière année n'étaient pas des échecs d'API. Il s'agissait d'une erreur d'indentation à deux espaces dans une configuration CI, et le point de terminaison n'a jamais été déployé du tout. (Yaml a un mode de défaillance plus catastrophique qu'une construction cassée, cependant : YAML valide, cela signifie quelque chose que vous n'aviez pas l'intention de faire. j'ai écrit pourquoi
version: 1.10devient 1.1 Après cela m'a coûté un déploiement.) - testeur de regex — Pour le moment, vous devez extraire un ID de requête sur 900 lignes de journaux avec un motif dont vous n'êtes pas sûr.
- Visionneuse CSV — Pour le point de terminaison d'exportation dont vous devez vérifier la sortie de santé avant que quelqu'un ne l'importe en production.
Est-ce vraiment important que ceux-ci s'exécutent dans le navigateur ?
Oui, et je dirais ceci même si je n'avais pas construit le site.
Pensez à ce que vous collez dans un outil de débogage. Un JWT - qui est un identifiant en direct jusqu'à son expiration. Une réponse à une API de production, qui est une donnée client : noms, e-mails, états d'abonnement. Un corps de webhook, qui peut contenir un enregistrement de paiement. un curl commander avec un Authorization En-tête toujours dedans.
Considérez maintenant qu'un outil côté serveur, par définition, reçoit tout cela. Pas de manière malveillante - juste sur le plan architectural. La pâte entre dans une requête HTTP, frappe le backend de quelqu'un et atterrit dans la journalisation qu'il exécute. Même un opérateur scrupuleusement honnête se retrouve avec votre jeton de porteur dans un journal d'accès qu'il n'a jamais eu l'intention de conserver.
Les outils sur Toolz.dev font le travail en JavaScript dans votre onglet. Rien n'est téléchargé, car il n'y a nulle part où le télécharger - l'analyse, le décodage, le hachage se produisent sur votre machine. Vous n'avez pas à me croire sur parole non plus : ouvrez DevTools, allez dans l'onglet Réseau, collez un jeton et surveillez une demande qui ne vient jamais. C'est un audit de trente-deuxième, et vous devriez l'exécuter sur n'importe lequel Outil dans lequel vous collez des secrets, le mien inclus. j'ai écrit Comment vérifier correctement un outil côté client Pour cette raison exactement.
Si votre organisation gère les données personnelles de l'UE, ce n'est pas seulement l'hygiène - coller les dossiers des clients dans un serveur tiers est une activité de traitement, avec tous les documents GDPR qui impliquent. Les outils côté client évitent la question en ne devenant jamais un processeur.
Un flux de travail qui colle en fait
Six étapes, dans l'ordre, je les exécute quand quelque chose est en feu :
- Capturez la réponse brute. Corps complet, en-têtes complets, code d'état. Pas l'interprétation de votre application - les octets réels.
curl -iou les onglets du réseau "Copier en tant que curl". - formatez-le. Formateur JSON. Regardez le forme Avant de regarder les valeurs. Le champ dont vous avez besoin est-il même présent ?
- Décodez chaque chaîne opaque. jetons à travers le Décodeur JWT, Base64 Blobs à travers le Convertisseur de base64, URL mutilées à travers le Encodeur d'URL. Les chaînes opaques masquent la réponse étonnamment.
- Transformez chaque nombre qui pourrait être une heure en date. Convertisseur d'horodatage. Comptez les chiffres en premier.
- Diff contre une réponse bonne connue. Diff JSON. Si vous n'avez pas de réponse bien connue, c'est votre signe de commencer à les enregistrer.
- Seulement maintenant, allez lire votre code. À ce stade, vous connaissez généralement la ligne avant d'ouvrir le fichier.
La commande compte. L'étape 6 est l'endroit où j'avais l'habitude de commencer, et c'est pourquoi ce samedi a pris huit heures.
Questions fréquentes
Quels sont les meilleurs outils gratuits pour déboguer des API ?
Pour le débogage d'API au jour le jour, vous avez besoin de cinq choses : un formateur et un validateur JSON, un décodeur JWT, un convertisseur d'horodatage Unix, un outil de diff et un encodeur/décodeur d'URL. Tous les cinq sont gratuits sur Toolz.dev et s'exécutent entièrement dans le navigateur. Ajoutez un générateur de hachage si vous travaillez avec des webhooks signés et un validateur YAML si vos déploiements sont basés sur la configuration.
Est-il sûr de coller une réponse JWT ou API dans un outil en ligne ?
Uniquement si l'outil est côté client. Un JWT est un identifiant en direct et une réponse à une API est généralement une donnée client, donc un outil côté serveur signifie expédier les deux dans le backend d'un étranger. Les outils Toolz.dev traitent tout ce qui se trouve dans votre navigateur avec JavaScript et n'envoyez rien sur le réseau. Vérifiez cela vous-même en ouvrant l'onglet Réseau de DevTools pendant que vous collez. Exécutez la même vérification sur n'importe quel outil que vous utilisez avec des données sensibles.
Pourquoi mon JWT dit-il "expiré" alors que je viens de le générer ?
La cause la plus fréquente est une incompatibilité avec les unités. le exp La revendication est en secondes (RFC 7519 le définit comme une date numérique), mais JavaScript Date.now() Renvoie des millisecondes, donc leur comparaison directement rend chaque jeton expiré. Décoder le jeton, lire exp, convertissez-le en une date réelle avec un convertisseur d'horodatage et vérifiez s'il est réellement dans le passé avant de toucher votre code d'authentification.
Comment savoir si un horodatage Unix est en secondes ou en millisecondes ?
Comptez les chiffres. Dix chiffres, c'est quelques secondes, treize, c'est une milliseconde, seize est une microseconde. Si une date sort en 1970, vous avez alimenté des secondes à un analyseur en millisecondes ; si elle sort dans l'année 56122, vous avez alimenté des millisecondes à un analyseur de seconde. La deuxième erreur est plus dangereuse car rien ne déclenche une erreur.
Puis-je utiliser ces outils pour déboguer les API GraphQL ?
Oui. Les réponses GraphQL sont JSON, de sorte que le formateur JSON et le format JSON Diff fonctionnent inchangés, et GraphQL utilise généralement la même authentification au porteur que vous décodez avec le décodeur JWT. La seule vraie différence est que GraphQL renvoie HTTP 200 avec un errors Array au lieu d'un statut non-2xx, donc formatez toujours le corps - la panne est dans la charge utile, pas dans le code d'état.
Pourquoi la vérification de ma signature Webhook échoue-t-elle toujours ?
Presque toujours parce que vous hachez des octets différents de ceux du fournisseur. Si votre cadre a analysé le corps JSON et que vous l'avez re-sérialisé avant de hacher, l'espace blanc ou l'ordre des clés a changé et le HMAC ne correspondra jamais. Hachez le corps de la requête brute exactement comme reçu et recherchez une nouvelle ligne de fin de ligne ajoutée par votre client HTTP.
Quelle est la différence entre l'encodage Base64 et Base64URL ?
Utilisation standard de la base64 (RFC 4648 §4) + et / dans son alphabet et des pads avec =. Base64URL (RFC 4648 §5) remplace ceux par - et _ Et laisse généralement tomber le rembourrage, de sorte que la valeur est sûre pour mettre une URL ou un JWT. L'alimentation des données de base64url dans un décodeur Standard-Base64 strict produit une erreur ou une ordure, c'est pourquoi un décodeur JWT dédié bat un jeton à la main.
Comment déboguer une réponse non autorisée 401 ?
Travaillez vers l'extérieur à partir du jeton. Décodez-le et vérifiez exp Contre l'heure actuelle - Un jeton expiré est la cause la plus courante, et il est invisible jusqu'à ce que vous convertissiez la réclamation en date lisible. Si le jeton est en direct, vérifiez le Authorization En-tête lui-même : le schéma doit être présent et orthographié correctement (Bearer <token>, un espace, sans guillemets) et un jeton collé à partir d'un terminal porte souvent une nouvelle ligne de fin qui casse le match. Après cela, confirmez la aud et iss Les réclamations correspondent à ce que l'API attend, car un jeton valide émis pour un public différent est rejeté exactement comme un mauvais. Alors seulement commencez à soupçonner le serveur.
Comment décoder un JWT sans bibliothèque ?
Un JWT est composé de trois segments Base64URL rejoints par des points. Divisez les points, puis décodez les deux premiers – l'en-tête et la charge utile – et les deux sortent en JSON. Le troisième segment est la signature et ne décode rien en lisible car il s'agit d'octets bruts plutôt que de texte. Cela compte plus que cela n'y paraît : le décodage d'un jeton vous indique ce qu'il prétend, et non si ces affirmations sont vraies. La vérification de la signature nécessite la clé de l'émetteur et appartient à votre code de serveur, jamais dans un outil de navigateur. Lisez les jetons ici pour déboguer, validez-les dans l'application.
Ai-je encore besoin de postman ou d'insomnie si j'utilise ces outils ?
Oui, ils résolvent des problèmes différents. Un client API envoie des demandes, ces outils rendent les réponses lisibles. En pratique, j'utilise le client pour lancer la requête et copier la sortie brute, puis passer aux outils du navigateur pour formater, décoder, convertir et differ. Ils s'assoient l'un à côté de l'autre dans le flux de travail plutôt que de se remplacer.

