@jjlmoya/utils-developer 1.16.0 → 1.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/category/index.ts +2 -1
- package/src/entries.ts +4 -1
- package/src/index.ts +2 -0
- package/src/tests/locale_completeness.test.ts +2 -2
- package/src/tests/tool_validation.test.ts +2 -2
- package/src/tool/jwtDecoder/bibliography.astro +14 -0
- package/src/tool/jwtDecoder/bibliography.ts +12 -0
- package/src/tool/jwtDecoder/component.astro +209 -0
- package/src/tool/jwtDecoder/entry.ts +30 -0
- package/src/tool/jwtDecoder/i18n/de.ts +248 -0
- package/src/tool/jwtDecoder/i18n/en.ts +247 -0
- package/src/tool/jwtDecoder/i18n/es.ts +248 -0
- package/src/tool/jwtDecoder/i18n/fr.ts +248 -0
- package/src/tool/jwtDecoder/i18n/id.ts +248 -0
- package/src/tool/jwtDecoder/i18n/it.ts +248 -0
- package/src/tool/jwtDecoder/i18n/ja.ts +248 -0
- package/src/tool/jwtDecoder/i18n/ko.ts +248 -0
- package/src/tool/jwtDecoder/i18n/nl.ts +247 -0
- package/src/tool/jwtDecoder/i18n/pl.ts +247 -0
- package/src/tool/jwtDecoder/i18n/pt.ts +247 -0
- package/src/tool/jwtDecoder/i18n/ru.ts +248 -0
- package/src/tool/jwtDecoder/i18n/sv.ts +248 -0
- package/src/tool/jwtDecoder/i18n/tr.ts +248 -0
- package/src/tool/jwtDecoder/i18n/zh.ts +248 -0
- package/src/tool/jwtDecoder/index.ts +11 -0
- package/src/tool/jwtDecoder/jwt-decoder-parser-and-claims-inspector.css +358 -0
- package/src/tool/jwtDecoder/logic.ts +96 -0
- package/src/tool/jwtDecoder/seo.astro +15 -0
- package/src/tool/jwtDecoder/ui.ts +38 -0
- package/src/tool/serpPixelSimulator/bibliography.astro +11 -4
- package/src/tool/serpPixelSimulator/index.ts +0 -4
- package/src/tool/serpPixelSimulator/seo.astro +8 -5
- package/src/tools.ts +2 -1
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { JwtDecoderUI } from '../ui';
|
|
4
|
+
import { bibliography } from '../bibliography';
|
|
5
|
+
|
|
6
|
+
const slug = 'decodeur-jwt-parser-et-inspecteur-de-claims';
|
|
7
|
+
const title = 'Décodeur JWT, Parser et Inspecteur de Claims';
|
|
8
|
+
const description = 'Collez un JSON Web Token, décodez son en-tête et son payload instantanément, inspectez les claims enregistrés, repérez les tokens expirés et copiez du JSON propre pour déboguer les flux d\'authentification.';
|
|
9
|
+
|
|
10
|
+
const howTo = [
|
|
11
|
+
{
|
|
12
|
+
name: 'Collez le JWT',
|
|
13
|
+
text: 'Copiez un token depuis un en-tête Authorization, un cookie, une entrée de log ou un fournisseur d\'identité et collez-le dans le champ de saisie.',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: 'Lisez l\'en-tête et le payload décodés',
|
|
17
|
+
text: 'L\'outil divise le token en en-tête, payload et signature, puis affiche les segments JSON dans des panneaux séparés pour une inspection rapide.',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'Vérifiez les claims importants',
|
|
21
|
+
text: 'Examinez l\'algorithme, l\'émetteur, l\'audience, le sujet, la date d\'émission, la date de début de validité et la date d\'expiration sans convertir manuellement les timestamps Unix.',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'Copiez les données dont vous avez besoin',
|
|
25
|
+
text: 'Copiez une section décodée ou la sortie décodée complète lorsque vous devez partager un instantané de débogage assaini avec votre équipe.',
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
const faq = [
|
|
30
|
+
{
|
|
31
|
+
question: 'Décoder un JWT prouve-t-il que le token est valide ?',
|
|
32
|
+
answer: 'Non. Le décodage révèle uniquement l\'en-tête et le payload encodés en base64url. Un token n\'est digne de confiance qu\'après que la signature, l\'émetteur, l\'audience, l\'expiration et les claims associés ont été validés par l\'application ou le fournisseur d\'identité.',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
question: 'Puis-je utiliser ce décodeur JWT pour les access tokens et les ID tokens ?',
|
|
36
|
+
answer: 'Oui. Le décodeur est utile pour inspecter les access tokens OAuth, les ID tokens OpenID Connect, les tokens de session et les tokens service à service, tant qu\'ils utilisent le format JWT standard en trois parties.',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
question: 'Pourquoi le panneau de signature ne vérifie-t-il pas le token ?',
|
|
40
|
+
answer: 'La vérification JWT nécessite le secret correct, la clé publique ou la configuration JWKS. Cet outil se concentre intentionnellement sur le décodage et l\'inspection afin que les développeurs puissent voir le contenu du token sans prétendre qu\'une chaîne de signature visible constitue une preuve de validité.',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
question: 'Que dois-je vérifier en premier lors du débogage d\'un JWT ?',
|
|
44
|
+
answer: 'Commencez par exp, nbf, iss, aud et alg. La plupart des problèmes réels en production proviennent de tokens expirés, de décalage d\'horloge, de valeurs d\'audience incorrectes, d\'URL d\'émetteur inattendues ou d\'hypothèses d\'algorithme non sécurisées.',
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const ui: JwtDecoderUI = {
|
|
49
|
+
tokenLabel: 'Token JWT',
|
|
50
|
+
tokenPlaceholder: 'Collez un JWT ici: en-tête.payload.signature',
|
|
51
|
+
sampleButton: 'Charger l\'exemple',
|
|
52
|
+
clearButton: 'Effacer',
|
|
53
|
+
statusWaiting: 'Collez un token pour décoder son en-tête JSON, son payload et ses claims.',
|
|
54
|
+
statusValid: 'JWT décodé avec succès.',
|
|
55
|
+
statusInvalid: 'Cela ne ressemble pas à un JWT valide en trois parties.',
|
|
56
|
+
statusExpired: 'JWT décodé, mais le claim exp est déjà expiré.',
|
|
57
|
+
statusUnsigned: 'JWT décodé, mais il n\'est pas signé ou utilise l\'algorithme none.',
|
|
58
|
+
headerTitle: 'En-tête',
|
|
59
|
+
payloadTitle: 'Payload',
|
|
60
|
+
signatureTitle: 'Signature',
|
|
61
|
+
claimsTitle: 'Claims enregistrés',
|
|
62
|
+
copyHeader: 'Copier l\'en-tête décodé',
|
|
63
|
+
copyPayload: 'Copier le payload décodé',
|
|
64
|
+
copySignature: 'Copier la signature',
|
|
65
|
+
copyAll: 'Tout copier',
|
|
66
|
+
copiedLabel: 'Copié',
|
|
67
|
+
invalidTokenTitle: 'JWT invalide',
|
|
68
|
+
invalidTokenBody: 'Vérifiez que le token comporte trois segments base64url séparés par des points.',
|
|
69
|
+
invalidSegmentError: 'Vérifiez que le token comporte trois segments base64url séparés par des points.',
|
|
70
|
+
invalidDecodeError: 'L\'en-tête ou le payload n\'a pas pu être décodé en JSON valide.',
|
|
71
|
+
emptyJson: '{}',
|
|
72
|
+
signaturePresent: 'Le segment de signature est présent ; vérifiez-le dans votre couche d\'authentification avec la clé appropriée.',
|
|
73
|
+
signatureMissing: 'Aucun segment de signature',
|
|
74
|
+
algorithmLabel: 'Algorithme',
|
|
75
|
+
typeLabel: 'Type',
|
|
76
|
+
issuerLabel: 'Émetteur',
|
|
77
|
+
subjectLabel: 'Sujet',
|
|
78
|
+
audienceLabel: 'Audience',
|
|
79
|
+
issuedAtLabel: 'Émis le',
|
|
80
|
+
notBeforeLabel: 'Valide à partir du',
|
|
81
|
+
expiresAtLabel: 'Expiré le',
|
|
82
|
+
claimMissing: 'Non présent',
|
|
83
|
+
privacyNote: 'Le décodage s\'exécute dans votre navigateur. Ne collez pas de secrets de production dans un outil, sauf si votre politique de sécurité l\'autorise.',
|
|
84
|
+
sampleToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJnYW1lYm9iLXVzZXItNDIiLCJuYW1lIjoiR2FtZUJvYiBEZXZlbG9wZXIiLCJpc3MiOiJodHRwczovL3d3dy5nYW1lYm9iLmRldiIsImF1ZCI6ImRldmVsb3Blci10b29scyIsImlhdCI6MTcxNzIwMDAwMCwibmJmIjoxNzE3MjAwMDAwLCJleHAiOjE4OTM0NTYwMDAsInJvbGUiOiJhZG1pbiJ9.demo-signature',
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
88
|
+
'@context': 'https://schema.org',
|
|
89
|
+
'@type': 'FAQPage',
|
|
90
|
+
mainEntity: faq.map((item) => ({
|
|
91
|
+
'@type': 'Question',
|
|
92
|
+
name: item.question,
|
|
93
|
+
acceptedAnswer: {
|
|
94
|
+
'@type': 'Answer',
|
|
95
|
+
text: item.answer,
|
|
96
|
+
},
|
|
97
|
+
})),
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const howToSchema: WithContext<HowTo> = {
|
|
101
|
+
'@context': 'https://schema.org',
|
|
102
|
+
'@type': 'HowTo',
|
|
103
|
+
name: title,
|
|
104
|
+
description,
|
|
105
|
+
step: howTo.map((step, index) => ({
|
|
106
|
+
'@type': 'HowToStep',
|
|
107
|
+
position: index + 1,
|
|
108
|
+
name: step.name,
|
|
109
|
+
text: step.text,
|
|
110
|
+
})),
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
114
|
+
'@context': 'https://schema.org',
|
|
115
|
+
'@type': 'SoftwareApplication',
|
|
116
|
+
name: title,
|
|
117
|
+
description,
|
|
118
|
+
applicationCategory: 'DeveloperApplication',
|
|
119
|
+
operatingSystem: 'Any',
|
|
120
|
+
offers: {
|
|
121
|
+
'@type': 'Offer',
|
|
122
|
+
price: '0',
|
|
123
|
+
priceCurrency: 'EUR',
|
|
124
|
+
},
|
|
125
|
+
inLanguage: 'fr',
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export const content: ToolLocaleContent<JwtDecoderUI> = {
|
|
129
|
+
slug,
|
|
130
|
+
title,
|
|
131
|
+
description,
|
|
132
|
+
ui,
|
|
133
|
+
faqTitle: 'FAQ du décodeur JWT',
|
|
134
|
+
faq,
|
|
135
|
+
bibliographyTitle: 'Spécifications JWT et références de sécurité',
|
|
136
|
+
bibliography,
|
|
137
|
+
howTo,
|
|
138
|
+
schemas: [appSchema, faqSchema, howToSchema],
|
|
139
|
+
seo: [
|
|
140
|
+
{
|
|
141
|
+
type: 'title',
|
|
142
|
+
text: 'Décodez les JWT sans perdre le contexte de sécurité',
|
|
143
|
+
level: 2,
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
type: 'paragraph',
|
|
147
|
+
html: 'Un JSON Web Token semble compact, mais il contient souvent le détail exact qui explique un échec d\'authentification: l\'algorithme de signature, l\'émetteur, l\'audience, le sujet, la date d\'émission, la date de début de validité, l\'expiration et les claims d\'autorisation spécifiques à l\'application. Ce <strong>décodeur JWT, parser et inspecteur de claims</strong> transforme les trois segments du token en JSON lisible pour que vous puissiez déboguer les flux d\'authentification plus rapidement.',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
type: 'diagnostic',
|
|
151
|
+
variant: 'warning',
|
|
152
|
+
title: 'Décodé ne signifie pas digne de confiance',
|
|
153
|
+
html: 'N\'importe qui peut décoder un JWT en base64url. La confiance ne commence qu\'après que votre application a vérifié la signature avec le secret, la clé publique ou le JWKS appropriés, puis validé l\'émetteur, l\'audience, l\'expiration et tout claim spécifique au domaine. Utilisez cet outil pour inspecter les données, pas pour accepter un token comme authentique.',
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
type: 'title',
|
|
157
|
+
text: 'Ce que chaque segment JWT vous dit',
|
|
158
|
+
level: 3,
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
type: 'table',
|
|
162
|
+
headers: ['Segment', 'Contenu typique', 'Valeur de débogage'],
|
|
163
|
+
rows: [
|
|
164
|
+
['En-tête', 'Algorithme, type de token et ID de clé optionnel', 'Indique si le token attend HS256, RS256, ES256 ou une autre stratégie de vérification.'],
|
|
165
|
+
['Payload', 'Claims enregistrés et claims d\'application', 'Révèle l\'identité, le tenant, les scopes, les rôles, l\'expiration et les décalages d\'audience.'],
|
|
166
|
+
['Signature', 'Octets de signature cryptographique encodés en base64url', 'Confirme qu\'un segment de signature existe, mais doit être vérifié avec la bonne clé ailleurs.'],
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
type: 'title',
|
|
171
|
+
text: 'Claims qui expliquent généralement les échecs d\'authentification',
|
|
172
|
+
level: 3,
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
type: 'list',
|
|
176
|
+
items: [
|
|
177
|
+
'<strong>exp:</strong> si le token a expiré, la logique de renouvellement ou les paramètres d\'horloge peuvent être incorrects.',
|
|
178
|
+
'<strong>nbf:</strong> si le token n\'est pas encore actif, les horloges du serveur et du fournisseur d\'identité peuvent être désynchronisées.',
|
|
179
|
+
'<strong>iss:</strong> si l\'URL de l\'émetteur diffère de la configuration, le token peut provenir d\'un mauvais tenant ou environnement.',
|
|
180
|
+
'<strong>aud:</strong> si l\'audience ne correspond pas à l\'identifiant de l\'API, le token a été émis pour une autre ressource.',
|
|
181
|
+
'<strong>alg:</strong> si l\'algorithme est inattendu, votre vérificateur peut rejeter le token ou exposer une erreur de configuration dangereuse.',
|
|
182
|
+
],
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
type: 'title',
|
|
186
|
+
text: 'Cas d\'utilisation d\'un parser JWT pendant le développement',
|
|
187
|
+
level: 3,
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
type: 'comparative',
|
|
191
|
+
columns: 3,
|
|
192
|
+
items: [
|
|
193
|
+
{
|
|
194
|
+
title: 'Débogage frontend',
|
|
195
|
+
description: 'Inspectez les ID tokens et access tokens reçus après la connexion pour confirmer les scopes, les rôles et les claims de profil.',
|
|
196
|
+
icon: 'mdi:monitor-dashboard',
|
|
197
|
+
points: ['Vérifiez les claims de profil', 'Confirmez les scopes et rôles', 'Comparez les environnements de connexion'],
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
title: 'QA d\'API backend',
|
|
201
|
+
description: 'Comparez les valeurs attendues de l\'émetteur et de l\'audience avec le token réellement envoyé dans un en-tête Authorization.',
|
|
202
|
+
icon: 'mdi:api',
|
|
203
|
+
highlight: true,
|
|
204
|
+
points: ['Validez la forme de l\'audience', 'Repérez les décalages d\'émetteur', 'Inspectez les bearer tokens'],
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
title: 'Configuration du fournisseur d\'identité',
|
|
208
|
+
description: 'Vérifiez si les claims d\'Auth0, Azure AD, Cognito, Keycloak ou d\'un fournisseur personnalisé sont structurés comme votre application l\'attend.',
|
|
209
|
+
icon: 'mdi:account-key',
|
|
210
|
+
points: ['Examinez les données du tenant', 'Vérifiez les claims personnalisés', 'Comparez les mappings du fournisseur'],
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
type: 'title',
|
|
216
|
+
text: 'Erreurs JWT courantes que cet inspecteur rend évidentes',
|
|
217
|
+
level: 3,
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
type: 'proscons',
|
|
221
|
+
title: 'Vérifications rapides contre décisions de confiance',
|
|
222
|
+
items: [
|
|
223
|
+
{
|
|
224
|
+
pro: 'Voyez les tokens mal formés immédiatement.',
|
|
225
|
+
con: 'Il ne peut pas connaître votre audience ou émetteur attendu.',
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
pro: 'Convertissez les claims de timestamp Unix en dates lisibles.',
|
|
229
|
+
con: 'Il ne peut pas vérifier une signature sans le matériel de clé réel.',
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
pro: 'Repérez les valeurs manquantes d\'émetteur, d\'audience, de sujet ou de type.',
|
|
233
|
+
con: 'Il ne peut pas prouver que les scopes et les rôles sont sûrs pour votre application.',
|
|
234
|
+
},
|
|
235
|
+
],
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
type: 'summary',
|
|
239
|
+
title: 'Flux de travail recommandé',
|
|
240
|
+
items: [
|
|
241
|
+
'Décodez le token pour comprendre ce que le client ou l\'API a réellement reçu.',
|
|
242
|
+
'Vérifiez exp, nbf, iss, aud, sub et alg avant de poursuivre la logique applicative.',
|
|
243
|
+
'Vérifiez les signatures et les décisions de confiance uniquement dans votre couche d\'authentification.',
|
|
244
|
+
'Évitez de partager des JWT de production sensibles dans les tickets, les logs ou les captures d\'écran.',
|
|
245
|
+
],
|
|
246
|
+
},
|
|
247
|
+
],
|
|
248
|
+
};
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import type { WithContext, FAQPage, HowTo, SoftwareApplication } from 'schema-dts';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
import type { JwtDecoderUI } from '../ui';
|
|
4
|
+
import { bibliography } from '../bibliography';
|
|
5
|
+
|
|
6
|
+
const slug = 'decoder-jwt-parser-dan-inspektur-klaim';
|
|
7
|
+
const title = 'Decoder JWT, Parser dan Inspektur Klaim';
|
|
8
|
+
const description = 'Tempelkan JSON Web Token, dekode header dan payload secara instan, periksa klaim terdaftar, temukan token yang sudah kedaluwarsa, dan salin JSON bersih untuk men-debug alur autentikasi.';
|
|
9
|
+
|
|
10
|
+
const howTo = [
|
|
11
|
+
{
|
|
12
|
+
name: 'Tempelkan JWT',
|
|
13
|
+
text: 'Salin token dari header Authorization, cookie, entri log, atau penyedia identitas dan tempelkan ke kolom input.',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: 'Baca header dan payload yang telah didekode',
|
|
17
|
+
text: 'Alat ini memisahkan token menjadi header, payload, dan tanda tangan, lalu menampilkan segmen JSON di panel terpisah untuk pemeriksaan cepat.',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'Periksa klaim penting',
|
|
21
|
+
text: 'Tinjau algoritma, penerbit, audiens, subjek, waktu penerbitan, waktu tidak sebelum, dan waktu kedaluwarsa tanpa mengonversi timestamp Unix secara manual.',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'Salin data yang Anda butuhkan',
|
|
25
|
+
text: 'Salin satu bagian yang didekode atau keluaran yang didekode lengkap saat Anda perlu membagikan cuplikan debugging yang sudah dibersihkan dengan tim Anda.',
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
const faq = [
|
|
30
|
+
{
|
|
31
|
+
question: 'Apakah mendekode JWT membuktikan bahwa token tersebut valid?',
|
|
32
|
+
answer: 'Tidak. Dekode hanya mengungkap header dan payload yang dikode base64url. Token hanya dapat dipercaya setelah tanda tangan, penerbit, audiens, kedaluwarsa, dan klaim terkait divalidasi oleh aplikasi atau penyedia identitas.',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
question: 'Bisakah saya menggunakan decoder JWT ini untuk access token dan ID token?',
|
|
36
|
+
answer: 'Ya. Decoder ini berguna untuk memeriksa access token OAuth, ID token OpenID Connect, token sesi, dan token layanan ke layanan, selama menggunakan format JWT tiga bagian standar.',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
question: 'Mengapa panel tanda tangan tidak memverifikasi token?',
|
|
40
|
+
answer: 'Verifikasi JWT memerlukan secret, kunci publik, atau konfigurasi JWKS yang benar. Alat ini sengaja berfokus pada dekode dan inspeksi sehingga pengembang dapat melihat isi token tanpa berpura pura bahwa string tanda tangan yang terlihat adalah bukti validitas.',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
question: 'Apa yang harus saya periksa terlebih dahulu saat men-debug JWT?',
|
|
44
|
+
answer: 'Mulai dengan exp, nbf, iss, aud, dan alg. Sebagian besar masalah produksi nyata berasal dari token yang sudah kedaluwarsa, selisih jam, nilai audiens yang salah, URL penerbit yang tidak terduga, atau asumsi algoritma yang tidak aman.',
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const ui: JwtDecoderUI = {
|
|
49
|
+
tokenLabel: 'Token JWT',
|
|
50
|
+
tokenPlaceholder: 'Tempelkan JWT di sini: header.payload.tanda tangan',
|
|
51
|
+
sampleButton: 'Muat contoh',
|
|
52
|
+
clearButton: 'Bersihkan',
|
|
53
|
+
statusWaiting: 'Tempelkan token untuk mendekode header JSON, payload, dan klaim.',
|
|
54
|
+
statusValid: 'JWT berhasil didekode.',
|
|
55
|
+
statusInvalid: 'Ini tidak terlihat seperti JWT tiga bagian yang valid.',
|
|
56
|
+
statusExpired: 'JWT didekode, tetapi klaim exp sudah kedaluwarsa.',
|
|
57
|
+
statusUnsigned: 'JWT didekode, tetapi tidak ditandatangani atau menggunakan algoritma none.',
|
|
58
|
+
headerTitle: 'Header',
|
|
59
|
+
payloadTitle: 'Payload',
|
|
60
|
+
signatureTitle: 'Tanda tangan',
|
|
61
|
+
claimsTitle: 'Klaim terdaftar',
|
|
62
|
+
copyHeader: 'Salin header yang didekode',
|
|
63
|
+
copyPayload: 'Salin payload yang didekode',
|
|
64
|
+
copySignature: 'Salin tanda tangan',
|
|
65
|
+
copyAll: 'Salin semua',
|
|
66
|
+
copiedLabel: 'Tersalin',
|
|
67
|
+
invalidTokenTitle: 'JWT tidak valid',
|
|
68
|
+
invalidTokenBody: 'Periksa apakah token memiliki tiga segmen base64url yang dipisahkan oleh titik.',
|
|
69
|
+
invalidSegmentError: 'Periksa apakah token memiliki tiga segmen base64url yang dipisahkan oleh titik.',
|
|
70
|
+
invalidDecodeError: 'Header atau payload tidak dapat didekode sebagai JSON yang valid.',
|
|
71
|
+
emptyJson: '{}',
|
|
72
|
+
signaturePresent: 'Segmen tanda tangan ada; verifikasi di lapisan autentikasi Anda dengan kunci yang benar.',
|
|
73
|
+
signatureMissing: 'Tidak ada segmen tanda tangan',
|
|
74
|
+
algorithmLabel: 'Algoritma',
|
|
75
|
+
typeLabel: 'Tipe',
|
|
76
|
+
issuerLabel: 'Penerbit',
|
|
77
|
+
subjectLabel: 'Subjek',
|
|
78
|
+
audienceLabel: 'Audiens',
|
|
79
|
+
issuedAtLabel: 'Diterbitkan pada',
|
|
80
|
+
notBeforeLabel: 'Tidak sebelum',
|
|
81
|
+
expiresAtLabel: 'Kedaluwarsa pada',
|
|
82
|
+
claimMissing: 'Tidak ada',
|
|
83
|
+
privacyNote: 'Dekode berjalan di sesi browser Anda. Jangan tempelkan secret produksi ke alat apa pun kecuali kebijakan keamanan Anda mengizinkannya.',
|
|
84
|
+
sampleToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJnYW1lYm9iLXVzZXItNDIiLCJuYW1lIjoiR2FtZUJvYiBEZXZlbG9wZXIiLCJpc3MiOiJodHRwczovL3d3dy5nYW1lYm9iLmRldiIsImF1ZCI6ImRldmVsb3Blci10b29scyIsImlhdCI6MTcxNzIwMDAwMCwibmJmIjoxNzE3MjAwMDAwLCJleHAiOjE4OTM0NTYwMDAsInJvbGUiOiJhZG1pbiJ9.demo-signature',
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const faqSchema: WithContext<FAQPage> = {
|
|
88
|
+
'@context': 'https://schema.org',
|
|
89
|
+
'@type': 'FAQPage',
|
|
90
|
+
mainEntity: faq.map((item) => ({
|
|
91
|
+
'@type': 'Question',
|
|
92
|
+
name: item.question,
|
|
93
|
+
acceptedAnswer: {
|
|
94
|
+
'@type': 'Answer',
|
|
95
|
+
text: item.answer,
|
|
96
|
+
},
|
|
97
|
+
})),
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const howToSchema: WithContext<HowTo> = {
|
|
101
|
+
'@context': 'https://schema.org',
|
|
102
|
+
'@type': 'HowTo',
|
|
103
|
+
name: title,
|
|
104
|
+
description,
|
|
105
|
+
step: howTo.map((step, index) => ({
|
|
106
|
+
'@type': 'HowToStep',
|
|
107
|
+
position: index + 1,
|
|
108
|
+
name: step.name,
|
|
109
|
+
text: step.text,
|
|
110
|
+
})),
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const appSchema: WithContext<SoftwareApplication> = {
|
|
114
|
+
'@context': 'https://schema.org',
|
|
115
|
+
'@type': 'SoftwareApplication',
|
|
116
|
+
name: title,
|
|
117
|
+
description,
|
|
118
|
+
applicationCategory: 'DeveloperApplication',
|
|
119
|
+
operatingSystem: 'Any',
|
|
120
|
+
offers: {
|
|
121
|
+
'@type': 'Offer',
|
|
122
|
+
price: '0',
|
|
123
|
+
priceCurrency: 'EUR',
|
|
124
|
+
},
|
|
125
|
+
inLanguage: 'id',
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export const content: ToolLocaleContent<JwtDecoderUI> = {
|
|
129
|
+
slug,
|
|
130
|
+
title,
|
|
131
|
+
description,
|
|
132
|
+
ui,
|
|
133
|
+
faqTitle: 'FAQ decoder JWT',
|
|
134
|
+
faq,
|
|
135
|
+
bibliographyTitle: 'Spesifikasi JWT dan referensi keamanan',
|
|
136
|
+
bibliography,
|
|
137
|
+
howTo,
|
|
138
|
+
schemas: [appSchema, faqSchema, howToSchema],
|
|
139
|
+
seo: [
|
|
140
|
+
{
|
|
141
|
+
type: 'title',
|
|
142
|
+
text: 'Dekode JWT tanpa kehilangan konteks keamanan',
|
|
143
|
+
level: 2,
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
type: 'paragraph',
|
|
147
|
+
html: 'JSON Web Token terlihat ringkas, tetapi sering kali membawa detail tepat yang menjelaskan kegagalan autentikasi: algoritma penandatanganan, penerbit, audiens, subjek, waktu penerbitan, waktu tidak sebelum, kedaluwarsa, dan klaim otorisasi khusus aplikasi. <strong>Decoder JWT, parser dan inspektur klaim</strong> ini mengubah tiga segmen token menjadi JSON yang dapat dibaca sehingga Anda dapat men-debug alur autentikasi lebih cepat.',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
type: 'diagnostic',
|
|
151
|
+
variant: 'warning',
|
|
152
|
+
title: 'Didekode bukan berarti terpercaya',
|
|
153
|
+
html: 'Siapa pun dapat mendekode JWT dengan base64url. Kepercayaan dimulai hanya setelah aplikasi Anda memverifikasi tanda tangan dengan secret, kunci publik, atau JWKS yang benar, lalu memvalidasi penerbit, audiens, kedaluwarsa, dan klaim khusus domain apa pun. Gunakan alat ini untuk memeriksa data, bukan untuk menerima token sebagai autentik.',
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
type: 'title',
|
|
157
|
+
text: 'Apa yang diungkapkan setiap segmen JWT',
|
|
158
|
+
level: 3,
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
type: 'table',
|
|
162
|
+
headers: ['Segmen', 'Konten umum', 'Nilai debugging'],
|
|
163
|
+
rows: [
|
|
164
|
+
['Header', 'Algoritma, tipe token, dan ID kunci opsional', 'Menunjukkan apakah token mengharapkan HS256, RS256, ES256, atau strategi verifikasi lainnya.'],
|
|
165
|
+
['Payload', 'Klaim terdaftar dan klaim aplikasi', 'Mengungkap identitas, tenant, scope, peran, kedaluwarsa, dan ketidakcocokan audiens.'],
|
|
166
|
+
['Tanda tangan', 'Byte tanda tangan kriptografis yang dikode sebagai base64url', 'Mengonfirmasi bahwa segmen tanda tangan ada, tetapi harus diverifikasi dengan kunci yang benar di tempat lain.'],
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
type: 'title',
|
|
171
|
+
text: 'Klaim yang biasanya menjelaskan kegagalan autentikasi',
|
|
172
|
+
level: 3,
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
type: 'list',
|
|
176
|
+
items: [
|
|
177
|
+
'<strong>exp:</strong> jika token sudah kedaluwarsa, logika refresh atau pengaturan jam mungkin salah.',
|
|
178
|
+
'<strong>nbf:</strong> jika token belum aktif, jam server dan penyedia identitas mungkin tidak sinkron.',
|
|
179
|
+
'<strong>iss:</strong> jika URL penerbit berbeda dari konfigurasi, token mungkin berasal dari tenant atau environment yang salah.',
|
|
180
|
+
'<strong>aud:</strong> jika audiens tidak cocok dengan pengenal API, token diterbitkan untuk sumber daya lain.',
|
|
181
|
+
'<strong>alg:</strong> jika algoritma tidak terduga, verifikator Anda mungkin menolak token atau mengekspos kesalahan konfigurasi yang berbahaya.',
|
|
182
|
+
],
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
type: 'title',
|
|
186
|
+
text: 'Kasus penggunaan parser JWT selama pengembangan',
|
|
187
|
+
level: 3,
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
type: 'comparative',
|
|
191
|
+
columns: 3,
|
|
192
|
+
items: [
|
|
193
|
+
{
|
|
194
|
+
title: 'Debugging frontend',
|
|
195
|
+
description: 'Periksa ID token dan access token yang diterima setelah login untuk mengonfirmasi scope, peran, dan klaim profil.',
|
|
196
|
+
icon: 'mdi:monitor-dashboard',
|
|
197
|
+
points: ['Periksa klaim profil', 'Konfirmasi scope dan peran', 'Bandingkan environment login'],
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
title: 'QA API backend',
|
|
201
|
+
description: 'Bandingkan nilai penerbit dan audiens yang diharapkan dengan token yang sebenarnya dikirim di header Authorization.',
|
|
202
|
+
icon: 'mdi:api',
|
|
203
|
+
highlight: true,
|
|
204
|
+
points: ['Validasi bentuk audiens', 'Temukan ketidakcocokan penerbit', 'Periksa bearer token'],
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
title: 'Pengaturan penyedia identitas',
|
|
208
|
+
description: 'Periksa apakah klaim dari Auth0, Azure AD, Cognito, Keycloak, atau penyedia kustom dibentuk seperti yang diharapkan aplikasi Anda.',
|
|
209
|
+
icon: 'mdi:account-key',
|
|
210
|
+
points: ['Tinjau data tenant', 'Periksa klaim kustom', 'Bandingkan pemetaan penyedia'],
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
type: 'title',
|
|
216
|
+
text: 'Kesalahan JWT umum yang dibuat jelas oleh inspektur ini',
|
|
217
|
+
level: 3,
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
type: 'proscons',
|
|
221
|
+
title: 'Pemeriksaan cepat versus keputusan kepercayaan',
|
|
222
|
+
items: [
|
|
223
|
+
{
|
|
224
|
+
pro: 'Lihat token yang salah format secara langsung.',
|
|
225
|
+
con: 'Tidak dapat mengetahui audiens atau penerbit yang Anda harapkan.',
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
pro: 'Konversi klaim timestamp Unix menjadi tanggal yang dapat dibaca.',
|
|
229
|
+
con: 'Tidak dapat memverifikasi tanda tangan tanpa materi kunci asli.',
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
pro: 'Temukan nilai penerbit, audiens, subjek, atau tipe yang hilang.',
|
|
233
|
+
con: 'Tidak dapat membuktikan bahwa scope dan peran aman untuk aplikasi Anda.',
|
|
234
|
+
},
|
|
235
|
+
],
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
type: 'summary',
|
|
239
|
+
title: 'Alur kerja praktik terbaik',
|
|
240
|
+
items: [
|
|
241
|
+
'Dekode token untuk memahami apa yang sebenarnya diterima oleh klien atau API.',
|
|
242
|
+
'Periksa exp, nbf, iss, aud, sub, dan alg sebelum mengejar logika aplikasi.',
|
|
243
|
+
'Verifikasi tanda tangan dan keputusan kepercayaan hanya di lapisan autentikasi Anda.',
|
|
244
|
+
'Hindari membagikan JWT produksi yang sensitif di tiket, log, atau tangkapan layar.',
|
|
245
|
+
],
|
|
246
|
+
},
|
|
247
|
+
],
|
|
248
|
+
};
|