@jjlmoya/utils-developer 1.30.0 → 1.32.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 +70 -70
- package/src/category/i18n/en.ts +1 -1
- package/src/category/i18n/es.ts +1 -1
- package/src/category/index.ts +2 -1
- package/src/category/seo.astro +1 -1
- package/src/components/PreviewNavSidebar.astro +1 -1
- package/src/components/PreviewToolbar.astro +1 -1
- package/src/data.ts +1 -1
- package/src/entries.ts +2 -0
- package/src/env.d.ts +1 -1
- package/src/index.ts +1 -0
- package/src/layouts/PreviewLayout.astro +1 -1
- package/src/pages/[locale]/[slug].astro +161 -161
- package/src/pages/index.astro +1 -1
- package/src/tests/bibliography_wellformed_export.test.ts +46 -0
- package/src/tests/category_seo_quality.test.ts +76 -0
- package/src/tests/entry_contract.test.ts +8 -2
- package/src/tests/faq_count.test.ts +1 -1
- package/src/tests/i18n_coverage.test.ts +2 -6
- package/src/tests/inverted_punctuation.test.ts +113 -113
- package/src/tests/locale_completeness.test.ts +1 -1
- package/src/tests/mocks/astro_mock.js +1 -1
- package/src/tests/no_h1_in_components.test.ts +1 -1
- package/src/tests/promote_this_website_i18n.test.ts +33 -0
- package/src/tests/seo_translation_completeness.test.ts +69 -0
- package/src/tests/seo_wellformed_export.test.ts +65 -0
- package/src/tests/slug_language_code_format.test.ts +25 -25
- package/src/tests/slug_uniqueness.test.ts +86 -86
- package/src/tests/tool_validation.test.ts +16 -16
- package/src/tool/aspectRatio/i18n/de.ts +164 -164
- package/src/tool/aspectRatio/i18n/ja.ts +1 -1
- package/src/tool/aspectRatio/i18n/ko.ts +1 -1
- package/src/tool/aspectRatio/i18n/pl.ts +164 -164
- package/src/tool/aspectRatio/i18n/ru.ts +164 -164
- package/src/tool/aspectRatio/i18n/zh.ts +165 -165
- package/src/tool/aspectRatio/seo.astro +15 -15
- package/src/tool/calculadoraTiempoDatos/i18n/de.ts +143 -143
- package/src/tool/calculadoraTiempoDatos/i18n/ja.ts +1 -1
- package/src/tool/calculadoraTiempoDatos/i18n/ko.ts +1 -1
- package/src/tool/calculadoraTiempoDatos/i18n/pl.ts +143 -143
- package/src/tool/calculadoraTiempoDatos/i18n/ru.ts +144 -144
- package/src/tool/calculadoraTiempoDatos/i18n/sv.ts +143 -143
- package/src/tool/calculadoraTiempoDatos/i18n/zh.ts +144 -144
- package/src/tool/calculadoraTiempoDatos/seo.astro +15 -15
- package/src/tool/colorConverter/i18n/de.ts +120 -120
- package/src/tool/colorConverter/i18n/ja.ts +1 -1
- package/src/tool/colorConverter/i18n/ko.ts +1 -1
- package/src/tool/colorConverter/i18n/ru.ts +120 -120
- package/src/tool/colorConverter/i18n/zh.ts +1 -1
- package/src/tool/colorConverter/seo.astro +15 -15
- package/src/tool/conversorExcelCsvHtml/i18n/ja.ts +1 -1
- package/src/tool/conversorExcelCsvHtml/i18n/ko.ts +1 -1
- package/src/tool/conversorExcelCsvHtml/i18n/pl.ts +124 -124
- package/src/tool/conversorExcelCsvHtml/i18n/ru.ts +124 -124
- package/src/tool/conversorExcelCsvHtml/i18n/zh.ts +125 -125
- package/src/tool/conversorExcelCsvHtml/seo.astro +15 -15
- package/src/tool/cronGenerator/i18n/ja.ts +1 -1
- package/src/tool/cronGenerator/i18n/ko.ts +1 -1
- package/src/tool/cronGenerator/i18n/zh.ts +183 -183
- package/src/tool/cronGenerator/seo.astro +15 -15
- package/src/tool/cssSpecificityCalculator/i18n/ja.ts +1 -1
- package/src/tool/cssSpecificityCalculator/i18n/ko.ts +1 -1
- package/src/tool/cssSpecificityCalculator/i18n/zh.ts +1 -1
- package/src/tool/cssSpecificityCalculator/seo.astro +15 -15
- package/src/tool/cssToInlineConverter/i18n/ja.ts +1 -1
- package/src/tool/cssToInlineConverter/i18n/ko.ts +1 -1
- package/src/tool/cssToInlineConverter/i18n/zh.ts +1 -1
- package/src/tool/cssToInlineConverter/seo.astro +15 -15
- package/src/tool/dualOsIconPreview/assets/day-check.webp +0 -0
- package/src/tool/dualOsIconPreview/assets/fast-task.webp +0 -0
- package/src/tool/dualOsIconPreview/assets/fortune-cookie.webp +0 -0
- package/src/tool/dualOsIconPreview/assets/lexi-crash.webp +0 -0
- package/src/tool/dualOsIconPreview/assets/pizzametrics.webp +0 -0
- package/src/tool/dualOsIconPreview/assets/sauce-lab.webp +0 -0
- package/src/tool/dualOsIconPreview/assets/vesp.webp +0 -0
- package/src/tool/dualOsIconPreview/bibliography.astro +6 -0
- package/src/tool/dualOsIconPreview/bibliography.ts +7 -0
- package/src/tool/dualOsIconPreview/component.astro +117 -0
- package/src/tool/dualOsIconPreview/controller.ts +157 -0
- package/src/tool/dualOsIconPreview/dom-views.ts +82 -0
- package/src/tool/dualOsIconPreview/dual-ios-android-app-icon-preview.css +861 -0
- package/src/tool/dualOsIconPreview/entry.ts +31 -0
- package/src/tool/dualOsIconPreview/evaluator.ts +20 -0
- package/src/tool/dualOsIconPreview/i18n/de.ts +56 -0
- package/src/tool/dualOsIconPreview/i18n/en.ts +46 -0
- package/src/tool/dualOsIconPreview/i18n/es.ts +56 -0
- package/src/tool/dualOsIconPreview/i18n/fr.ts +56 -0
- package/src/tool/dualOsIconPreview/i18n/id.ts +56 -0
- package/src/tool/dualOsIconPreview/i18n/it.ts +56 -0
- package/src/tool/dualOsIconPreview/i18n/ja.ts +56 -0
- package/src/tool/dualOsIconPreview/i18n/ko.ts +56 -0
- package/src/tool/dualOsIconPreview/i18n/nl.ts +56 -0
- package/src/tool/dualOsIconPreview/i18n/pl.ts +56 -0
- package/src/tool/dualOsIconPreview/i18n/pt.ts +56 -0
- package/src/tool/dualOsIconPreview/i18n/ru.ts +56 -0
- package/src/tool/dualOsIconPreview/i18n/sv.ts +56 -0
- package/src/tool/dualOsIconPreview/i18n/tr.ts +43 -0
- package/src/tool/dualOsIconPreview/i18n/zh.ts +43 -0
- package/src/tool/dualOsIconPreview/index.ts +11 -0
- package/src/tool/dualOsIconPreview/logic.test.ts +63 -0
- package/src/tool/dualOsIconPreview/logic.ts +135 -0
- package/src/tool/dualOsIconPreview/seo.astro +15 -0
- package/src/tool/dualOsIconPreview/storage.ts +18 -0
- package/src/tool/dualOsIconPreview/ui.ts +52 -0
- package/src/tool/duplicateCssRemover/i18n/ja.ts +1 -1
- package/src/tool/duplicateCssRemover/i18n/ko.ts +1 -1
- package/src/tool/duplicateCssRemover/i18n/zh.ts +1 -1
- package/src/tool/duplicateCssRemover/seo.astro +15 -15
- package/src/tool/generadorSecurityTxt/i18n/ja.ts +1 -1
- package/src/tool/generadorSecurityTxt/i18n/ko.ts +1 -1
- package/src/tool/generadorSecurityTxt/i18n/zh.ts +1 -1
- package/src/tool/generadorSecurityTxt/seo.astro +15 -15
- package/src/tool/hashGenerator/i18n/ja.ts +1 -1
- package/src/tool/hashGenerator/i18n/ko.ts +1 -1
- package/src/tool/hashGenerator/seo.astro +15 -15
- package/src/tool/inspectorCertificadosSsl/i18n/ja.ts +1 -1
- package/src/tool/inspectorCertificadosSsl/i18n/ko.ts +1 -1
- package/src/tool/inspectorCertificadosSsl/i18n/zh.ts +1 -1
- package/src/tool/inspectorCertificadosSsl/seo.astro +15 -15
- package/src/tool/jsonFormatter/seo.astro +15 -15
- package/src/tool/jwtDecoder/i18n/es.ts +248 -248
- package/src/tool/jwtDecoder/i18n/fr.ts +248 -248
- package/src/tool/jwtDecoder/i18n/tr.ts +248 -248
- package/src/tool/keycode/seo.astro +15 -15
- package/src/tool/llmCostCalculator/i18n/fr.ts +149 -149
- package/src/tool/llmCostCalculator/i18n/ja.ts +1 -1
- package/src/tool/llmCostCalculator/i18n/ko.ts +1 -1
- package/src/tool/llmCostCalculator/seo.astro +15 -15
- package/src/tool/mobileMockupGenerator/i18n/ja.ts +1 -1
- package/src/tool/mobileMockupGenerator/i18n/ko.ts +1 -1
- package/src/tool/mobileMockupGenerator/i18n/zh.ts +1 -1
- package/src/tool/mobileMockupGenerator/seo.astro +15 -15
- package/src/tool/musicalTypography/i18n/ja.ts +1 -1
- package/src/tool/musicalTypography/i18n/ko.ts +1 -1
- package/src/tool/musicalTypography/i18n/zh.ts +1 -1
- package/src/tool/musicalTypography/seo.astro +15 -15
- package/src/tool/placeholderGenerator/i18n/ja.ts +1 -1
- package/src/tool/placeholderGenerator/i18n/ko.ts +1 -1
- package/src/tool/placeholderGenerator/i18n/zh.ts +1 -1
- package/src/tool/placeholderGenerator/seo.astro +15 -15
- package/src/tool/promoteThisWebsite/entry.ts +13 -0
- package/src/tool/promoteThisWebsite/i18n/de.ts +95 -0
- package/src/tool/promoteThisWebsite/i18n/fr.ts +95 -0
- package/src/tool/promoteThisWebsite/i18n/id.ts +95 -0
- package/src/tool/promoteThisWebsite/i18n/it.ts +95 -0
- package/src/tool/promoteThisWebsite/i18n/ja.ts +95 -0
- package/src/tool/promoteThisWebsite/i18n/ko.ts +95 -0
- package/src/tool/promoteThisWebsite/i18n/nl.ts +95 -0
- package/src/tool/promoteThisWebsite/i18n/pl.ts +95 -0
- package/src/tool/promoteThisWebsite/i18n/pt.ts +95 -0
- package/src/tool/promoteThisWebsite/i18n/ru.ts +95 -0
- package/src/tool/promoteThisWebsite/i18n/sv.ts +95 -0
- package/src/tool/promoteThisWebsite/i18n/tr.ts +95 -0
- package/src/tool/promoteThisWebsite/i18n/zh.ts +95 -0
- package/src/tool/promptLibrary/i18n/ja.ts +1 -1
- package/src/tool/promptLibrary/i18n/ko.ts +1 -1
- package/src/tool/promptLibrary/i18n/zh.ts +1 -1
- package/src/tool/promptLibrary/seo.astro +15 -15
- package/src/tool/readabilityCalculator/i18n/ja.ts +1 -1
- package/src/tool/readabilityCalculator/i18n/ko.ts +1 -1
- package/src/tool/readabilityCalculator/i18n/zh.ts +1 -1
- package/src/tool/readabilityCalculator/seo.astro +15 -15
- package/src/tool/serpPixelSimulator/entry.ts +30 -30
- package/src/tool/serpPixelSimulator/i18n/en.ts +211 -211
- package/src/tool/serpPixelSimulator/i18n/fr.ts +214 -214
- package/src/tool/serpPixelSimulator/i18n/ru.ts +214 -214
- package/src/tool/serpPixelSimulator/logic.ts +18 -18
- package/src/tool/serpPixelSimulator/serp-pixel-simulator.css +195 -195
- package/src/tool/svgSanitizer/i18n/ja.ts +1 -1
- package/src/tool/svgSanitizer/i18n/ko.ts +1 -1
- package/src/tool/svgSanitizer/seo.astro +15 -15
- package/src/tool/svgToCss/i18n/ja.ts +1 -1
- package/src/tool/svgToCss/i18n/ko.ts +1 -1
- package/src/tool/svgToCss/seo.astro +15 -15
- package/src/tool/urlCleaner/i18n/ja.ts +1 -1
- package/src/tool/urlCleaner/i18n/ko.ts +1 -1
- package/src/tool/urlCleaner/i18n/zh.ts +1 -1
- package/src/tool/urlCleaner/seo.astro +15 -15
- package/src/tool/urlEncoderDecoder/i18n/es.ts +146 -146
- package/src/tool/urlEncoderDecoder/i18n/ko.ts +1 -1
- package/src/tool/urlEncoderDecoder/seo.astro +15 -15
- package/src/tool/utmGenerator/i18n/ja.ts +1 -1
- package/src/tool/utmGenerator/i18n/ko.ts +1 -1
- package/src/tool/utmGenerator/i18n/zh.ts +1 -1
- package/src/tool/utmGenerator/seo.astro +15 -15
- package/src/tools.ts +2 -1
- package/src/types.ts +1 -1
|
@@ -1,248 +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 = 'decodificador-jwt-parser-e-inspector-de-claims';
|
|
7
|
-
const title = 'Decodificador JWT, Parser e Inspector de Claims';
|
|
8
|
-
const description = 'Pega un JSON Web Token, decodifica su cabecera y payload al instante, inspecciona claims registrados, detecta tokens expirados y copia JSON limpio para depurar flujos de autenticación.';
|
|
9
|
-
|
|
10
|
-
const howTo = [
|
|
11
|
-
{
|
|
12
|
-
name: 'Pega el JWT',
|
|
13
|
-
text: 'Copia un token de una cabecera Authorization, cookie, entrada de log o proveedor de identidad y pégalo en el campo de entrada.',
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
name: 'Lee la cabecera y el payload decodificados',
|
|
17
|
-
text: 'La herramienta divide el token en cabecera, payload y firma, luego muestra los segmentos JSON en paneles separados para una inspección rápida.',
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
name: 'Comprueba los claims importantes',
|
|
21
|
-
text: 'Revisa el algoritmo, emisor, audiencia, sujeto, fecha de emisión, fecha de validez inicial y fecha de expiración sin convertir manualmente timestamps Unix.',
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
name: 'Copia los datos que necesitas',
|
|
25
|
-
text: 'Copia una sección decodificada o la salida decodificada completa cuando necesites compartir una instantánea de depuración saneada con tu equipo.',
|
|
26
|
-
},
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
const faq = [
|
|
30
|
-
{
|
|
31
|
-
question: '¿Decodificar un JWT demuestra que el token es válido?',
|
|
32
|
-
answer: 'No. Decodificar solo revela la cabecera y el payload codificados en base64url. Un token es confiable solo después de que la firma, el emisor, la audiencia, la expiración y los claims relacionados sean validados por la aplicación o el proveedor de identidad.',
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
question: '¿Puedo usar este decodificador JWT para access tokens e ID tokens?',
|
|
36
|
-
answer: 'Sí. El decodificador es útil para inspeccionar access tokens OAuth, ID tokens OpenID Connect, tokens de sesión y tokens servicio a servicio, siempre que usen el formato JWT estándar de tres partes.',
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
question: '¿Por qué el panel de firma no verifica el token?',
|
|
40
|
-
answer: 'La verificación JWT requiere el secreto correcto, la clave pública o la configuración JWKS. Esta herramienta se centra intencionadamente en la decodificación e inspección para que los desarrolladores puedan ver el contenido del token sin pretender que una cadena de firma visible es prueba de validez.',
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
question: '¿Qué debo comprobar primero al depurar un JWT?',
|
|
44
|
-
answer: 'Empieza por exp, nbf, iss, aud y alg. La mayoría de los problemas reales en producción provienen de tokens expirados, desfase de reloj, valores de audiencia incorrectos, URLs de emisor inesperadas o suposiciones inseguras sobre el algoritmo.',
|
|
45
|
-
},
|
|
46
|
-
];
|
|
47
|
-
|
|
48
|
-
const ui: JwtDecoderUI = {
|
|
49
|
-
tokenLabel: 'Token JWT',
|
|
50
|
-
tokenPlaceholder: 'Pega un JWT aquí: cabecera.payload.firma',
|
|
51
|
-
sampleButton: 'Cargar ejemplo',
|
|
52
|
-
clearButton: 'Limpiar',
|
|
53
|
-
statusWaiting: 'Pega un token para decodificar su cabecera JSON, payload y claims.',
|
|
54
|
-
statusValid: 'JWT decodificado correctamente.',
|
|
55
|
-
statusInvalid: 'Esto no parece un JWT válido de tres partes.',
|
|
56
|
-
statusExpired: 'JWT decodificado, pero el claim exp ya está expirado.',
|
|
57
|
-
statusUnsigned: 'JWT decodificado, pero no está firmado o usa el algoritmo none.',
|
|
58
|
-
headerTitle: 'Cabecera',
|
|
59
|
-
payloadTitle: 'Payload',
|
|
60
|
-
signatureTitle: 'Firma',
|
|
61
|
-
claimsTitle: 'Claims registrados',
|
|
62
|
-
copyHeader: 'Copiar cabecera decodificada',
|
|
63
|
-
copyPayload: 'Copiar payload decodificado',
|
|
64
|
-
copySignature: 'Copiar firma',
|
|
65
|
-
copyAll: 'Copiar todo',
|
|
66
|
-
copiedLabel: 'Copiado',
|
|
67
|
-
invalidTokenTitle: 'JWT no válido',
|
|
68
|
-
invalidTokenBody: 'Comprueba que el token tiene tres segmentos base64url separados por puntos.',
|
|
69
|
-
invalidSegmentError: 'Comprueba que el token tiene tres segmentos base64url separados por puntos.',
|
|
70
|
-
invalidDecodeError: 'La cabecera o el payload no se pudieron decodificar como JSON válido.',
|
|
71
|
-
emptyJson: '{}',
|
|
72
|
-
signaturePresent: 'El segmento de firma está presente; verifícalo en tu capa de autenticación con la clave correcta.',
|
|
73
|
-
signatureMissing: 'Sin segmento de firma',
|
|
74
|
-
algorithmLabel: 'Algoritmo',
|
|
75
|
-
typeLabel: 'Tipo',
|
|
76
|
-
issuerLabel: 'Emisor',
|
|
77
|
-
subjectLabel: 'Sujeto',
|
|
78
|
-
audienceLabel: 'Audiencia',
|
|
79
|
-
issuedAtLabel: 'Emitido el',
|
|
80
|
-
notBeforeLabel: 'No antes del',
|
|
81
|
-
expiresAtLabel: 'Expira el',
|
|
82
|
-
claimMissing: 'No presente',
|
|
83
|
-
privacyNote: 'La decodificación se ejecuta en tu navegador. No pegues secretos de producción en ninguna herramienta a menos que tu política de seguridad lo permita.',
|
|
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: 'es',
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
export const content: ToolLocaleContent<JwtDecoderUI> = {
|
|
129
|
-
slug,
|
|
130
|
-
title,
|
|
131
|
-
description,
|
|
132
|
-
ui,
|
|
133
|
-
faqTitle: 'Preguntas frecuentes sobre el decodificador JWT',
|
|
134
|
-
faq,
|
|
135
|
-
bibliographyTitle: 'Especificaciones JWT y referencias de seguridad',
|
|
136
|
-
bibliography,
|
|
137
|
-
howTo,
|
|
138
|
-
schemas: [appSchema, faqSchema, howToSchema],
|
|
139
|
-
seo: [
|
|
140
|
-
{
|
|
141
|
-
type: 'title',
|
|
142
|
-
text: 'Decodifica JWTs sin perder el contexto de seguridad',
|
|
143
|
-
level: 2,
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
type: 'paragraph',
|
|
147
|
-
html: 'Un JSON Web Token parece compacto, pero a menudo contiene el detalle exacto que explica un fallo de autenticación: el algoritmo de firma, emisor, audiencia, sujeto, fecha de emisión, fecha de validez inicial, expiración y claims de autorización específicos de la aplicación. Este <strong>decodificador JWT, parser e inspector de claims</strong> convierte los tres segmentos del token en JSON legible para que puedas depurar flujos de autenticación más rápido.',
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
type: 'diagnostic',
|
|
151
|
-
variant: 'warning',
|
|
152
|
-
title: 'Decodificado no significa confiable',
|
|
153
|
-
html: 'Cualquiera puede decodificar un JWT en base64url. La confianza comienza solo después de que tu aplicación verifique la firma con el secreto, clave pública o JWKS correctos y luego valide el emisor, la audiencia, la expiración y cualquier claim específico del dominio. Usa esta herramienta para inspeccionar datos, no para aceptar un token como auténtico.',
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
type: 'title',
|
|
157
|
-
text: 'Lo que te dice cada segmento JWT',
|
|
158
|
-
level: 3,
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
type: 'table',
|
|
162
|
-
headers: ['Segmento', 'Contenido típico', 'Valor de depuración'],
|
|
163
|
-
rows: [
|
|
164
|
-
['Cabecera', 'Algoritmo, tipo de token e ID de clave opcional', 'Muestra si el token espera HS256, RS256, ES256 u otra estrategia de verificación.'],
|
|
165
|
-
['Payload', 'Claims registrados y claims de aplicación', 'Revela identidad, tenant, scopes, roles, expiración y desajustes de audiencia.'],
|
|
166
|
-
['Firma', 'Bytes de firma criptográfica codificados como base64url', 'Confirma que existe un segmento de firma, pero debe verificarse con la clave correcta en otro lugar.'],
|
|
167
|
-
],
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
type: 'title',
|
|
171
|
-
text: 'Claims que suelen explicar fallos de autenticación',
|
|
172
|
-
level: 3,
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
type: 'list',
|
|
176
|
-
items: [
|
|
177
|
-
'<strong>exp:</strong> si el token expiró, la lógica de renovación o la configuración del reloj pueden estar mal.',
|
|
178
|
-
'<strong>nbf:</strong> si el token aún no está activo, los relojes del servidor y del proveedor de identidad pueden estar desincronizados.',
|
|
179
|
-
'<strong>iss:</strong> si la URL del emisor difiere de la configuración, el token puede venir del tenant o entorno equivocado.',
|
|
180
|
-
'<strong>aud:</strong> si la audiencia no coincide con el identificador de la API, el token fue emitido para otro recurso.',
|
|
181
|
-
'<strong>alg:</strong> si el algoritmo es inesperado, tu verificador puede rechazar el token o exponer un error de configuración peligroso.',
|
|
182
|
-
],
|
|
183
|
-
},
|
|
184
|
-
{
|
|
185
|
-
type: 'title',
|
|
186
|
-
text: 'Casos de uso de un parser JWT durante el desarrollo',
|
|
187
|
-
level: 3,
|
|
188
|
-
},
|
|
189
|
-
{
|
|
190
|
-
type: 'comparative',
|
|
191
|
-
columns: 3,
|
|
192
|
-
items: [
|
|
193
|
-
{
|
|
194
|
-
title: 'Depuración frontend',
|
|
195
|
-
description: 'Inspecciona ID tokens y access tokens recibidos tras el inicio de sesión para confirmar scopes, roles y claims de perfil.',
|
|
196
|
-
icon: 'mdi:monitor-dashboard',
|
|
197
|
-
points: ['Comprueba claims de perfil', 'Confirma scopes y roles', 'Compara entornos de login'],
|
|
198
|
-
},
|
|
199
|
-
{
|
|
200
|
-
title: 'QA de API backend',
|
|
201
|
-
description: 'Compara los valores esperados de emisor y audiencia con el token realmente enviado en una cabecera Authorization.',
|
|
202
|
-
icon: 'mdi:api',
|
|
203
|
-
highlight: true,
|
|
204
|
-
points: ['Valida la forma de la audiencia', 'Detecta desajustes de emisor', 'Inspecciona bearer tokens'],
|
|
205
|
-
},
|
|
206
|
-
{
|
|
207
|
-
title: 'Configuración del proveedor de identidad',
|
|
208
|
-
description: 'Comprueba si los claims de Auth0, Azure AD, Cognito, Keycloak o un proveedor personalizado tienen la forma que tu aplicación espera.',
|
|
209
|
-
icon: 'mdi:account-key',
|
|
210
|
-
points: ['Revisa datos del tenant', 'Comprueba claims personalizados', 'Compara mapeos del proveedor'],
|
|
211
|
-
},
|
|
212
|
-
],
|
|
213
|
-
},
|
|
214
|
-
{
|
|
215
|
-
type: 'title',
|
|
216
|
-
text: 'Errores comunes de JWT que este inspector hace evidentes',
|
|
217
|
-
level: 3,
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
type: 'proscons',
|
|
221
|
-
title: 'Comprobaciones rápidas frente a decisiones de confianza',
|
|
222
|
-
items: [
|
|
223
|
-
{
|
|
224
|
-
pro: 'Ve tokens mal formados inmediatamente.',
|
|
225
|
-
con: 'No puede conocer tu audiencia o emisor esperados.',
|
|
226
|
-
},
|
|
227
|
-
{
|
|
228
|
-
pro: 'Convierte claims de timestamp Unix en fechas legibles.',
|
|
229
|
-
con: 'No puede verificar una firma sin el material de clave real.',
|
|
230
|
-
},
|
|
231
|
-
{
|
|
232
|
-
pro: 'Detecta valores faltantes de emisor, audiencia, sujeto o tipo.',
|
|
233
|
-
con: 'No puede demostrar que los scopes y roles son seguros para tu aplicación.',
|
|
234
|
-
},
|
|
235
|
-
],
|
|
236
|
-
},
|
|
237
|
-
{
|
|
238
|
-
type: 'summary',
|
|
239
|
-
title: 'Flujo de trabajo recomendado',
|
|
240
|
-
items: [
|
|
241
|
-
'Decodifica el token para entender lo que el cliente o la API realmente recibieron.',
|
|
242
|
-
'Comprueba exp, nbf, iss, aud, sub y alg antes de perseguir la lógica de aplicación.',
|
|
243
|
-
'Verifica firmas y decisiones de confianza solo en tu capa de autenticación.',
|
|
244
|
-
'Evita compartir JWTs de producción sensibles en tickets, logs o capturas de pantalla.',
|
|
245
|
-
],
|
|
246
|
-
},
|
|
247
|
-
],
|
|
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 = 'decodificador-jwt-parser-e-inspector-de-claims';
|
|
7
|
+
const title = 'Decodificador JWT, Parser e Inspector de Claims';
|
|
8
|
+
const description = 'Pega un JSON Web Token, decodifica su cabecera y payload al instante, inspecciona claims registrados, detecta tokens expirados y copia JSON limpio para depurar flujos de autenticación.';
|
|
9
|
+
|
|
10
|
+
const howTo = [
|
|
11
|
+
{
|
|
12
|
+
name: 'Pega el JWT',
|
|
13
|
+
text: 'Copia un token de una cabecera Authorization, cookie, entrada de log o proveedor de identidad y pégalo en el campo de entrada.',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: 'Lee la cabecera y el payload decodificados',
|
|
17
|
+
text: 'La herramienta divide el token en cabecera, payload y firma, luego muestra los segmentos JSON en paneles separados para una inspección rápida.',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'Comprueba los claims importantes',
|
|
21
|
+
text: 'Revisa el algoritmo, emisor, audiencia, sujeto, fecha de emisión, fecha de validez inicial y fecha de expiración sin convertir manualmente timestamps Unix.',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'Copia los datos que necesitas',
|
|
25
|
+
text: 'Copia una sección decodificada o la salida decodificada completa cuando necesites compartir una instantánea de depuración saneada con tu equipo.',
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
const faq = [
|
|
30
|
+
{
|
|
31
|
+
question: '¿Decodificar un JWT demuestra que el token es válido?',
|
|
32
|
+
answer: 'No. Decodificar solo revela la cabecera y el payload codificados en base64url. Un token es confiable solo después de que la firma, el emisor, la audiencia, la expiración y los claims relacionados sean validados por la aplicación o el proveedor de identidad.',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
question: '¿Puedo usar este decodificador JWT para access tokens e ID tokens?',
|
|
36
|
+
answer: 'Sí. El decodificador es útil para inspeccionar access tokens OAuth, ID tokens OpenID Connect, tokens de sesión y tokens servicio a servicio, siempre que usen el formato JWT estándar de tres partes.',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
question: '¿Por qué el panel de firma no verifica el token?',
|
|
40
|
+
answer: 'La verificación JWT requiere el secreto correcto, la clave pública o la configuración JWKS. Esta herramienta se centra intencionadamente en la decodificación e inspección para que los desarrolladores puedan ver el contenido del token sin pretender que una cadena de firma visible es prueba de validez.',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
question: '¿Qué debo comprobar primero al depurar un JWT?',
|
|
44
|
+
answer: 'Empieza por exp, nbf, iss, aud y alg. La mayoría de los problemas reales en producción provienen de tokens expirados, desfase de reloj, valores de audiencia incorrectos, URLs de emisor inesperadas o suposiciones inseguras sobre el algoritmo.',
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const ui: JwtDecoderUI = {
|
|
49
|
+
tokenLabel: 'Token JWT',
|
|
50
|
+
tokenPlaceholder: 'Pega un JWT aquí: cabecera.payload.firma',
|
|
51
|
+
sampleButton: 'Cargar ejemplo',
|
|
52
|
+
clearButton: 'Limpiar',
|
|
53
|
+
statusWaiting: 'Pega un token para decodificar su cabecera JSON, payload y claims.',
|
|
54
|
+
statusValid: 'JWT decodificado correctamente.',
|
|
55
|
+
statusInvalid: 'Esto no parece un JWT válido de tres partes.',
|
|
56
|
+
statusExpired: 'JWT decodificado, pero el claim exp ya está expirado.',
|
|
57
|
+
statusUnsigned: 'JWT decodificado, pero no está firmado o usa el algoritmo none.',
|
|
58
|
+
headerTitle: 'Cabecera',
|
|
59
|
+
payloadTitle: 'Payload',
|
|
60
|
+
signatureTitle: 'Firma',
|
|
61
|
+
claimsTitle: 'Claims registrados',
|
|
62
|
+
copyHeader: 'Copiar cabecera decodificada',
|
|
63
|
+
copyPayload: 'Copiar payload decodificado',
|
|
64
|
+
copySignature: 'Copiar firma',
|
|
65
|
+
copyAll: 'Copiar todo',
|
|
66
|
+
copiedLabel: 'Copiado',
|
|
67
|
+
invalidTokenTitle: 'JWT no válido',
|
|
68
|
+
invalidTokenBody: 'Comprueba que el token tiene tres segmentos base64url separados por puntos.',
|
|
69
|
+
invalidSegmentError: 'Comprueba que el token tiene tres segmentos base64url separados por puntos.',
|
|
70
|
+
invalidDecodeError: 'La cabecera o el payload no se pudieron decodificar como JSON válido.',
|
|
71
|
+
emptyJson: '{}',
|
|
72
|
+
signaturePresent: 'El segmento de firma está presente; verifícalo en tu capa de autenticación con la clave correcta.',
|
|
73
|
+
signatureMissing: 'Sin segmento de firma',
|
|
74
|
+
algorithmLabel: 'Algoritmo',
|
|
75
|
+
typeLabel: 'Tipo',
|
|
76
|
+
issuerLabel: 'Emisor',
|
|
77
|
+
subjectLabel: 'Sujeto',
|
|
78
|
+
audienceLabel: 'Audiencia',
|
|
79
|
+
issuedAtLabel: 'Emitido el',
|
|
80
|
+
notBeforeLabel: 'No antes del',
|
|
81
|
+
expiresAtLabel: 'Expira el',
|
|
82
|
+
claimMissing: 'No presente',
|
|
83
|
+
privacyNote: 'La decodificación se ejecuta en tu navegador. No pegues secretos de producción en ninguna herramienta a menos que tu política de seguridad lo permita.',
|
|
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: 'es',
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export const content: ToolLocaleContent<JwtDecoderUI> = {
|
|
129
|
+
slug,
|
|
130
|
+
title,
|
|
131
|
+
description,
|
|
132
|
+
ui,
|
|
133
|
+
faqTitle: 'Preguntas frecuentes sobre el decodificador JWT',
|
|
134
|
+
faq,
|
|
135
|
+
bibliographyTitle: 'Especificaciones JWT y referencias de seguridad',
|
|
136
|
+
bibliography,
|
|
137
|
+
howTo,
|
|
138
|
+
schemas: [appSchema, faqSchema, howToSchema],
|
|
139
|
+
seo: [
|
|
140
|
+
{
|
|
141
|
+
type: 'title',
|
|
142
|
+
text: 'Decodifica JWTs sin perder el contexto de seguridad',
|
|
143
|
+
level: 2,
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
type: 'paragraph',
|
|
147
|
+
html: 'Un JSON Web Token parece compacto, pero a menudo contiene el detalle exacto que explica un fallo de autenticación: el algoritmo de firma, emisor, audiencia, sujeto, fecha de emisión, fecha de validez inicial, expiración y claims de autorización específicos de la aplicación. Este <strong>decodificador JWT, parser e inspector de claims</strong> convierte los tres segmentos del token en JSON legible para que puedas depurar flujos de autenticación más rápido.',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
type: 'diagnostic',
|
|
151
|
+
variant: 'warning',
|
|
152
|
+
title: 'Decodificado no significa confiable',
|
|
153
|
+
html: 'Cualquiera puede decodificar un JWT en base64url. La confianza comienza solo después de que tu aplicación verifique la firma con el secreto, clave pública o JWKS correctos y luego valide el emisor, la audiencia, la expiración y cualquier claim específico del dominio. Usa esta herramienta para inspeccionar datos, no para aceptar un token como auténtico.',
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
type: 'title',
|
|
157
|
+
text: 'Lo que te dice cada segmento JWT',
|
|
158
|
+
level: 3,
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
type: 'table',
|
|
162
|
+
headers: ['Segmento', 'Contenido típico', 'Valor de depuración'],
|
|
163
|
+
rows: [
|
|
164
|
+
['Cabecera', 'Algoritmo, tipo de token e ID de clave opcional', 'Muestra si el token espera HS256, RS256, ES256 u otra estrategia de verificación.'],
|
|
165
|
+
['Payload', 'Claims registrados y claims de aplicación', 'Revela identidad, tenant, scopes, roles, expiración y desajustes de audiencia.'],
|
|
166
|
+
['Firma', 'Bytes de firma criptográfica codificados como base64url', 'Confirma que existe un segmento de firma, pero debe verificarse con la clave correcta en otro lugar.'],
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
type: 'title',
|
|
171
|
+
text: 'Claims que suelen explicar fallos de autenticación',
|
|
172
|
+
level: 3,
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
type: 'list',
|
|
176
|
+
items: [
|
|
177
|
+
'<strong>exp:</strong> si el token expiró, la lógica de renovación o la configuración del reloj pueden estar mal.',
|
|
178
|
+
'<strong>nbf:</strong> si el token aún no está activo, los relojes del servidor y del proveedor de identidad pueden estar desincronizados.',
|
|
179
|
+
'<strong>iss:</strong> si la URL del emisor difiere de la configuración, el token puede venir del tenant o entorno equivocado.',
|
|
180
|
+
'<strong>aud:</strong> si la audiencia no coincide con el identificador de la API, el token fue emitido para otro recurso.',
|
|
181
|
+
'<strong>alg:</strong> si el algoritmo es inesperado, tu verificador puede rechazar el token o exponer un error de configuración peligroso.',
|
|
182
|
+
],
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
type: 'title',
|
|
186
|
+
text: 'Casos de uso de un parser JWT durante el desarrollo',
|
|
187
|
+
level: 3,
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
type: 'comparative',
|
|
191
|
+
columns: 3,
|
|
192
|
+
items: [
|
|
193
|
+
{
|
|
194
|
+
title: 'Depuración frontend',
|
|
195
|
+
description: 'Inspecciona ID tokens y access tokens recibidos tras el inicio de sesión para confirmar scopes, roles y claims de perfil.',
|
|
196
|
+
icon: 'mdi:monitor-dashboard',
|
|
197
|
+
points: ['Comprueba claims de perfil', 'Confirma scopes y roles', 'Compara entornos de login'],
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
title: 'QA de API backend',
|
|
201
|
+
description: 'Compara los valores esperados de emisor y audiencia con el token realmente enviado en una cabecera Authorization.',
|
|
202
|
+
icon: 'mdi:api',
|
|
203
|
+
highlight: true,
|
|
204
|
+
points: ['Valida la forma de la audiencia', 'Detecta desajustes de emisor', 'Inspecciona bearer tokens'],
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
title: 'Configuración del proveedor de identidad',
|
|
208
|
+
description: 'Comprueba si los claims de Auth0, Azure AD, Cognito, Keycloak o un proveedor personalizado tienen la forma que tu aplicación espera.',
|
|
209
|
+
icon: 'mdi:account-key',
|
|
210
|
+
points: ['Revisa datos del tenant', 'Comprueba claims personalizados', 'Compara mapeos del proveedor'],
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
type: 'title',
|
|
216
|
+
text: 'Errores comunes de JWT que este inspector hace evidentes',
|
|
217
|
+
level: 3,
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
type: 'proscons',
|
|
221
|
+
title: 'Comprobaciones rápidas frente a decisiones de confianza',
|
|
222
|
+
items: [
|
|
223
|
+
{
|
|
224
|
+
pro: 'Ve tokens mal formados inmediatamente.',
|
|
225
|
+
con: 'No puede conocer tu audiencia o emisor esperados.',
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
pro: 'Convierte claims de timestamp Unix en fechas legibles.',
|
|
229
|
+
con: 'No puede verificar una firma sin el material de clave real.',
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
pro: 'Detecta valores faltantes de emisor, audiencia, sujeto o tipo.',
|
|
233
|
+
con: 'No puede demostrar que los scopes y roles son seguros para tu aplicación.',
|
|
234
|
+
},
|
|
235
|
+
],
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
type: 'summary',
|
|
239
|
+
title: 'Flujo de trabajo recomendado',
|
|
240
|
+
items: [
|
|
241
|
+
'Decodifica el token para entender lo que el cliente o la API realmente recibieron.',
|
|
242
|
+
'Comprueba exp, nbf, iss, aud, sub y alg antes de perseguir la lógica de aplicación.',
|
|
243
|
+
'Verifica firmas y decisiones de confianza solo en tu capa de autenticación.',
|
|
244
|
+
'Evita compartir JWTs de producción sensibles en tickets, logs o capturas de pantalla.',
|
|
245
|
+
],
|
|
246
|
+
},
|
|
247
|
+
],
|
|
248
|
+
};
|