@jjlmoya/utils-developer 1.15.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 +3 -1
- package/src/entries.ts +7 -1
- package/src/index.ts +4 -0
- package/src/tests/locale_completeness.test.ts +2 -3
- package/src/tests/pagespeed_best_practices.test.ts +198 -0
- package/src/tests/tool_validation.test.ts +2 -2
- package/src/tool/aspectRatio/component.astro +3 -1
- package/src/tool/colorConverter/component.astro +3 -3
- 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/llmCostCalculator/component.astro +1 -2
- package/src/tool/mobileMockupGenerator/component.astro +4 -5
- package/src/tool/placeholderGenerator/component.astro +2 -2
- package/src/tool/readabilityCalculator/component.astro +4 -4
- package/src/tool/serpPixelSimulator/bibliography.astro +14 -0
- package/src/tool/serpPixelSimulator/bibliography.ts +16 -0
- package/src/tool/serpPixelSimulator/component.astro +84 -0
- package/src/tool/serpPixelSimulator/controller.ts +323 -0
- package/src/tool/serpPixelSimulator/entry.ts +30 -0
- package/src/tool/serpPixelSimulator/i18n/de.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/en.ts +213 -0
- package/src/tool/serpPixelSimulator/i18n/es.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/fr.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/id.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/it.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/ja.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/ko.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/nl.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/pl.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/pt.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/ru.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/sv.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/tr.ts +214 -0
- package/src/tool/serpPixelSimulator/i18n/zh.ts +214 -0
- package/src/tool/serpPixelSimulator/index.ts +8 -0
- package/src/tool/serpPixelSimulator/logic.ts +18 -0
- package/src/tool/serpPixelSimulator/seo.astro +15 -0
- package/src/tool/serpPixelSimulator/serp-pixel-simulator.css +335 -0
- package/src/tool/serpPixelSimulator/ui.ts +33 -0
- package/src/tools.ts +3 -2
|
@@ -0,0 +1,247 @@
|
|
|
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-inspetor-de-claims';
|
|
7
|
+
const title = 'Decodificador JWT, Parser e Inspetor de Claims';
|
|
8
|
+
const description = 'Cole um JSON Web Token, decodifique seu cabeçalho e payload instantaneamente, inspecione claims registradas, identifique tokens expirados e copie JSON limpo para depurar fluxos de autenticação.';
|
|
9
|
+
|
|
10
|
+
const howTo = [
|
|
11
|
+
{
|
|
12
|
+
name: 'Cole o JWT',
|
|
13
|
+
text: 'Copie um token de um cabeçalho Authorization, cookie, entrada de log ou provedor de identidade e cole-o no campo de entrada.',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: 'Leia o cabeçalho e payload decodificados',
|
|
17
|
+
text: 'A ferramenta divide o token em cabeçalho, payload e assinatura, depois renderiza os segmentos JSON em painéis separados para inspeção rápida.',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'Verifique claims importantes',
|
|
21
|
+
text: 'Revise algoritmo, emissor, audiência, assunto, data de emissão, data de validade inicial e data de expiração sem converter manualmente timestamps Unix.',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'Copie os dados necessários',
|
|
25
|
+
text: 'Copie uma seção decodificada ou a saída completa quando precisar compartilhar um snapshot de depuração higienizado com sua equipe.',
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
const faq = [
|
|
30
|
+
{
|
|
31
|
+
question: 'Decodificar um JWT prova que o token é válido?',
|
|
32
|
+
answer: 'Não. A decodificação apenas revela o cabeçalho e o payload codificados em base64url. Um token só é confiável depois que a assinatura, emissor, audiência, expiração e claims relacionadas são validadas pela aplicação ou provedor de identidade.',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
question: 'Posso usar este decodificador JWT para access tokens e ID tokens?',
|
|
36
|
+
answer: 'Sim. O decodificador é útil para inspecionar access tokens OAuth, ID tokens OpenID Connect, tokens de sessão e tokens serviço a serviço, desde que usem o formato JWT padrão de três partes.',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
question: 'Por que o painel de assinatura não verifica o token?',
|
|
40
|
+
answer: 'A verificação JWT requer o segredo correto, chave pública ou configuração JWKS. Esta ferramenta foca intencionalmente na decodificação e inspeção para que os desenvolvedores possam ver o conteúdo do token sem fingir que uma string de assinatura visível é prova de validade.',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
question: 'O que devo verificar primeiro ao depurar um JWT?',
|
|
44
|
+
answer: 'Comece com exp, nbf, iss, aud e alg. A maioria dos problemas reais de produção vem de tokens expirados, desvio de relógio, valores de audiência incorretos, URLs de emissor inesperadas ou suposições inseguras de algoritmo.',
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const ui: JwtDecoderUI = {
|
|
49
|
+
tokenLabel: 'Token JWT',
|
|
50
|
+
tokenPlaceholder: 'Cole um JWT aqui: cabeçalho.payload.assinatura',
|
|
51
|
+
sampleButton: 'Carregar exemplo',
|
|
52
|
+
clearButton: 'Limpar',
|
|
53
|
+
statusWaiting: 'Cole um token para decodificar seu cabeçalho JSON, payload e claims.',
|
|
54
|
+
statusValid: 'JWT decodificado com sucesso.',
|
|
55
|
+
statusInvalid: 'Isso não parece ser um JWT válido de três partes.',
|
|
56
|
+
statusExpired: 'JWT decodificado, mas a claim exp já está expirada.',
|
|
57
|
+
statusUnsigned: 'JWT decodificado, mas não está assinado ou usa algoritmo none.',
|
|
58
|
+
headerTitle: 'Cabeçalho',
|
|
59
|
+
payloadTitle: 'Payload',
|
|
60
|
+
signatureTitle: 'Assinatura',
|
|
61
|
+
claimsTitle: 'Claims registradas',
|
|
62
|
+
copyHeader: 'Copiar cabeçalho decodificado',
|
|
63
|
+
copyPayload: 'Copiar payload decodificado',
|
|
64
|
+
copySignature: 'Copiar assinatura',
|
|
65
|
+
copyAll: 'Copiar tudo',
|
|
66
|
+
copiedLabel: 'Copiado',
|
|
67
|
+
invalidTokenTitle: 'JWT inválido',
|
|
68
|
+
invalidTokenBody: 'Verifique se o token tem três segmentos base64url separados por pontos.',
|
|
69
|
+
invalidSegmentError: 'Verifique se o token tem três segmentos base64url separados por pontos.',
|
|
70
|
+
invalidDecodeError: 'O cabeçalho ou payload não pode ser decodificado como JSON válido.',
|
|
71
|
+
emptyJson: '{}',
|
|
72
|
+
signaturePresent: 'O segmento de assinatura está presente; verifique-o em sua camada de autenticação com a chave correta.',
|
|
73
|
+
signatureMissing: 'Nenhum segmento de assinatura',
|
|
74
|
+
algorithmLabel: 'Algoritmo',
|
|
75
|
+
typeLabel: 'Tipo',
|
|
76
|
+
issuerLabel: 'Emissor',
|
|
77
|
+
subjectLabel: 'Assunto',
|
|
78
|
+
audienceLabel: 'Audiência',
|
|
79
|
+
issuedAtLabel: 'Emitido em',
|
|
80
|
+
notBeforeLabel: 'Válido a partir de',
|
|
81
|
+
expiresAtLabel: 'Expira em',
|
|
82
|
+
claimMissing: 'Não presente',
|
|
83
|
+
privacyNote: 'A decodificação é executada no seu navegador. Não cole segredos de produção em nenhuma ferramenta a menos que sua política de segurança 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
|
+
};
|
|
126
|
+
|
|
127
|
+
export const content: ToolLocaleContent<JwtDecoderUI> = {
|
|
128
|
+
slug,
|
|
129
|
+
title,
|
|
130
|
+
description,
|
|
131
|
+
ui,
|
|
132
|
+
faqTitle: 'FAQ do decodificador JWT',
|
|
133
|
+
faq,
|
|
134
|
+
bibliographyTitle: 'Especificações JWT e referências de segurança',
|
|
135
|
+
bibliography,
|
|
136
|
+
howTo,
|
|
137
|
+
schemas: [appSchema, faqSchema, howToSchema],
|
|
138
|
+
seo: [
|
|
139
|
+
{
|
|
140
|
+
type: 'title',
|
|
141
|
+
text: 'Decodifique JWTs sem perder o contexto de segurança',
|
|
142
|
+
level: 2,
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
type: 'paragraph',
|
|
146
|
+
html: 'Um JSON Web Token parece compacto, mas frequentemente carrega o detalhe exato que explica uma falha de autenticação: o algoritmo de assinatura, emissor, audiência, assunto, data de emissão, data de validade inicial, expiração e claims de autorização específicas da aplicação. Este <strong>decodificador JWT, parser e inspetor de claims</strong> transforma os três segmentos do token em JSON legível para que você possa depurar fluxos de autenticação mais rapidamente.',
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
type: 'diagnostic',
|
|
150
|
+
variant: 'warning',
|
|
151
|
+
title: 'Decodificado não significa confiável',
|
|
152
|
+
html: 'Qualquer pessoa pode decodificar um JWT em base64url. A confiança começa apenas depois que sua aplicação verifica a assinatura com o segredo correto, chave pública ou JWKS, e então valida emissor, audiência, expiração e quaisquer claims específicas do domínio. Use esta ferramenta para inspecionar dados, não para aceitar um token como autêntico.',
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
type: 'title',
|
|
156
|
+
text: 'O que cada segmento JWT revela',
|
|
157
|
+
level: 3,
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
type: 'table',
|
|
161
|
+
headers: ['Segmento', 'Conteúdo típico', 'Valor para depuração'],
|
|
162
|
+
rows: [
|
|
163
|
+
['Cabeçalho', 'Algoritmo, tipo de token e ID de chave opcional', 'Mostra se o token espera HS256, RS256, ES256 ou outra estratégia de verificação.'],
|
|
164
|
+
['Payload', 'Claims registradas e claims da aplicação', 'Revela identidade, tenant, escopos, funções, expiração e incompatibilidades de audiência.'],
|
|
165
|
+
['Assinatura', 'Bytes de assinatura criptográfica codificados como base64url', 'Confirma que um segmento de assinatura existe, mas deve ser verificado com a chave correta em outro lugar.'],
|
|
166
|
+
],
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
type: 'title',
|
|
170
|
+
text: 'Claims que geralmente explicam falhas de autenticação',
|
|
171
|
+
level: 3,
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
type: 'list',
|
|
175
|
+
items: [
|
|
176
|
+
'<strong>exp:</strong> se o token expirou, a lógica de renovação ou as configurações de relógio podem estar erradas.',
|
|
177
|
+
'<strong>nbf:</strong> se o token ainda não está ativo, os relógios do servidor e do provedor de identidade podem estar dessincronizados.',
|
|
178
|
+
'<strong>iss:</strong> se a URL do emissor difere da configuração, o token pode vir do tenant ou ambiente errado.',
|
|
179
|
+
'<strong>aud:</strong> se a audiência não corresponde ao identificador da API, o token foi emitido para outro recurso.',
|
|
180
|
+
'<strong>alg:</strong> se o algoritmo é inesperado, seu verificador pode rejeitar o token ou expor um erro de configuração perigoso.',
|
|
181
|
+
],
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
type: 'title',
|
|
185
|
+
text: 'Casos de uso de um parser JWT durante o desenvolvimento',
|
|
186
|
+
level: 3,
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
type: 'comparative',
|
|
190
|
+
columns: 3,
|
|
191
|
+
items: [
|
|
192
|
+
{
|
|
193
|
+
title: 'Depuração frontend',
|
|
194
|
+
description: 'Inspecione ID tokens e access tokens recebidos após o login para confirmar escopos, funções e claims de perfil.',
|
|
195
|
+
icon: 'mdi:monitor-dashboard',
|
|
196
|
+
points: ['Verificar claims de perfil', 'Confirmar escopos e funções', 'Comparar ambientes de login'],
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
title: 'QA de API backend',
|
|
200
|
+
description: 'Compare valores esperados de emissor e audiência com o token realmente enviado no cabeçalho Authorization.',
|
|
201
|
+
icon: 'mdi:api',
|
|
202
|
+
highlight: true,
|
|
203
|
+
points: ['Validar formato da audiência', 'Identificar incompatibilidades de emissor', 'Inspecionar bearer tokens'],
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
title: 'Configuração de provedor de identidade',
|
|
207
|
+
description: 'Verifique se as claims do Auth0, Azure AD, Cognito, Keycloak ou um provedor personalizado estão formatadas como sua aplicação espera.',
|
|
208
|
+
icon: 'mdi:account-key',
|
|
209
|
+
points: ['Revisar dados do tenant', 'Verificar claims personalizadas', 'Comparar mapeamentos do provedor'],
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
type: 'title',
|
|
215
|
+
text: 'Erros comuns de JWT que este inspetor torna óbvios',
|
|
216
|
+
level: 3,
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
type: 'proscons',
|
|
220
|
+
title: 'Verificações rápidas versus decisões de confiança',
|
|
221
|
+
items: [
|
|
222
|
+
{
|
|
223
|
+
pro: 'Veja tokens malformados imediatamente.',
|
|
224
|
+
con: 'Não pode saber sua audiência ou emissor esperados.',
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
pro: 'Converta claims de timestamp Unix em datas legíveis.',
|
|
228
|
+
con: 'Não pode verificar uma assinatura sem o material de chave real.',
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
pro: 'Identifique valores ausentes de emissor, audiência, assunto ou tipo.',
|
|
232
|
+
con: 'Não pode provar que escopos e funções são seguros para sua aplicação.',
|
|
233
|
+
},
|
|
234
|
+
],
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
type: 'summary',
|
|
238
|
+
title: 'Fluxo de trabalho de melhores práticas',
|
|
239
|
+
items: [
|
|
240
|
+
'Decodifique o token para entender o que o cliente ou API realmente recebeu.',
|
|
241
|
+
'Verifique exp, nbf, iss, aud, sub e alg antes de buscar lógica de aplicação.',
|
|
242
|
+
'Verifique assinaturas e decisões de confiança apenas em sua camada de autenticação.',
|
|
243
|
+
'Evite compartilhar JWTs de produção sensíveis em tickets, logs ou capturas de tela.',
|
|
244
|
+
],
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
};
|
|
@@ -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 = 'dekoder-jwt-parser-inspector-claims';
|
|
7
|
+
const title = 'Декодер JWT, Парсер и Инспектор Claims';
|
|
8
|
+
const description = 'Вставьте JSON Web Token, мгновенно декодируйте его заголовок и полезную нагрузку, проверяйте зарегистрированные claims, находите просроченные токены и копируйте чистый JSON для отладки процессов аутентификации.';
|
|
9
|
+
|
|
10
|
+
const howTo = [
|
|
11
|
+
{
|
|
12
|
+
name: 'Вставьте JWT',
|
|
13
|
+
text: 'Скопируйте токен из заголовка Authorization, cookie, записи журнала или провайдера идентификации и вставьте его в поле ввода.',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: 'Прочитайте декодированные заголовок и payload',
|
|
17
|
+
text: 'Инструмент разделяет токен на заголовок, payload и подпись, затем отображает JSON сегменты на отдельных панелях для быстрой проверки.',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'Проверьте важные claims',
|
|
21
|
+
text: 'Проверьте алгоритм, издателя, аудиторию, субъект, время выпуска, время начала действия и срок истечения без ручного преобразования Unix timestamp.',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'Скопируйте нужные данные',
|
|
25
|
+
text: 'Скопируйте один декодированный раздел или весь декодированный вывод, когда нужно поделиться очищенным снимком отладки с командой.',
|
|
26
|
+
},
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
const faq = [
|
|
30
|
+
{
|
|
31
|
+
question: 'Доказывает ли декодирование JWT, что токен действителен?',
|
|
32
|
+
answer: 'Нет. Декодирование лишь раскрывает заголовок и payload в кодировке base64url. Токен заслуживает доверия только после того, как подпись, издатель, аудитория, срок действия и связанные claims проверены приложением или провайдером идентификации.',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
question: 'Можно ли использовать этот декодер JWT для access токенов и ID токенов?',
|
|
36
|
+
answer: 'Да. Декодер полезен для проверки OAuth access токенов, ID токенов OpenID Connect, сессионных токенов и токенов сервис-сервис, если они используют стандартный трёхчастный формат JWT.',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
question: 'Почему панель подписи не проверяет токен?',
|
|
40
|
+
answer: 'Для проверки JWT требуется правильный секрет, открытый ключ или конфигурация JWKS. Этот инструмент намеренно сосредоточен на декодировании и проверке, чтобы разработчики могли видеть содержимое токена, не выдавая видимую строку подписи за доказательство подлинности.',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
question: 'Что проверять в первую очередь при отладке JWT?',
|
|
44
|
+
answer: 'Начните с exp, nbf, iss, aud и alg. Большинство реальных производственных проблем связано с истёкшими токенами, рассинхронизацией часов, неверными значениями audience, неожиданными URL издателя или небезопасными предположениями об алгоритме.',
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
const ui: JwtDecoderUI = {
|
|
49
|
+
tokenLabel: 'JWT токен',
|
|
50
|
+
tokenPlaceholder: 'Вставьте JWT сюда: заголовок.payload.подпись',
|
|
51
|
+
sampleButton: 'Загрузить пример',
|
|
52
|
+
clearButton: 'Очистить',
|
|
53
|
+
statusWaiting: 'Вставьте токен для декодирования его JSON заголовка, payload и claims.',
|
|
54
|
+
statusValid: 'JWT успешно декодирован.',
|
|
55
|
+
statusInvalid: 'Это не похоже на действительный трёхчастный JWT.',
|
|
56
|
+
statusExpired: 'JWT декодирован, но claim exp уже истёк.',
|
|
57
|
+
statusUnsigned: 'JWT декодирован, но он не подписан или использует алгоритм none.',
|
|
58
|
+
headerTitle: 'Заголовок',
|
|
59
|
+
payloadTitle: 'Payload',
|
|
60
|
+
signatureTitle: 'Подпись',
|
|
61
|
+
claimsTitle: 'Зарегистрированные claims',
|
|
62
|
+
copyHeader: 'Копировать декодированный заголовок',
|
|
63
|
+
copyPayload: 'Копировать декодированный payload',
|
|
64
|
+
copySignature: 'Копировать подпись',
|
|
65
|
+
copyAll: 'Копировать всё',
|
|
66
|
+
copiedLabel: 'Скопировано',
|
|
67
|
+
invalidTokenTitle: 'Недействительный JWT',
|
|
68
|
+
invalidTokenBody: 'Проверьте, что токен содержит три сегмента base64url, разделённых точками.',
|
|
69
|
+
invalidSegmentError: 'Проверьте, что токен содержит три сегмента base64url, разделённых точками.',
|
|
70
|
+
invalidDecodeError: 'Заголовок или payload не удалось декодировать как действительный JSON.',
|
|
71
|
+
emptyJson: '{}',
|
|
72
|
+
signaturePresent: 'Сегмент подписи присутствует; проверьте его в вашем слое аутентификации с правильным ключом.',
|
|
73
|
+
signatureMissing: 'Сегмент подписи отсутствует',
|
|
74
|
+
algorithmLabel: 'Алгоритм',
|
|
75
|
+
typeLabel: 'Тип',
|
|
76
|
+
issuerLabel: 'Издатель',
|
|
77
|
+
subjectLabel: 'Субъект',
|
|
78
|
+
audienceLabel: 'Аудитория',
|
|
79
|
+
issuedAtLabel: 'Выпущен',
|
|
80
|
+
notBeforeLabel: 'Действует с',
|
|
81
|
+
expiresAtLabel: 'Истекает',
|
|
82
|
+
claimMissing: 'Отсутствует',
|
|
83
|
+
privacyNote: 'Декодирование выполняется в вашем браузере. Не вставляйте производственные секреты в инструмент, если это не разрешено вашей политикой безопасности.',
|
|
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: 'ru',
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export const content: ToolLocaleContent<JwtDecoderUI> = {
|
|
129
|
+
slug,
|
|
130
|
+
title,
|
|
131
|
+
description,
|
|
132
|
+
ui,
|
|
133
|
+
faqTitle: 'Часто задаваемые вопросы о декодере JWT',
|
|
134
|
+
faq,
|
|
135
|
+
bibliographyTitle: 'Спецификации JWT и ссылки по безопасности',
|
|
136
|
+
bibliography,
|
|
137
|
+
howTo,
|
|
138
|
+
schemas: [appSchema, faqSchema, howToSchema],
|
|
139
|
+
seo: [
|
|
140
|
+
{
|
|
141
|
+
type: 'title',
|
|
142
|
+
text: 'Декодируйте JWT, не теряя контекст безопасности',
|
|
143
|
+
level: 2,
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
type: 'paragraph',
|
|
147
|
+
html: 'JSON Web Token выглядит компактно, но часто содержит именно ту информацию, которая объясняет сбой аутентификации: алгоритм подписи, издатель, аудитория, субъект, время выпуска, время начала действия, срок истечения и специфичные для приложения claims авторизации. Этот <strong>декодер JWT, парсер и инспектор claims</strong> превращает три сегмента токена в читаемый JSON, чтобы вы могли быстрее отлаживать процессы аутентификации.',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
type: 'diagnostic',
|
|
151
|
+
variant: 'warning',
|
|
152
|
+
title: 'Декодировано не значит проверено',
|
|
153
|
+
html: 'Любой может декодировать JWT из base64url. Доверие начинается только после того, как ваше приложение проверит подпись с правильным секретом, открытым ключом или JWKS, а затем проверит издателя, аудиторию, срок действия и специфичные для домена claims. Используйте этот инструмент для проверки данных, а не для принятия токена как подлинного.',
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
type: 'title',
|
|
157
|
+
text: 'Что говорит каждый сегмент JWT',
|
|
158
|
+
level: 3,
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
type: 'table',
|
|
162
|
+
headers: ['Сегмент', 'Типичное содержимое', 'Ценность для отладки'],
|
|
163
|
+
rows: [
|
|
164
|
+
['Заголовок', 'Алгоритм, тип токена и опциональный ID ключа', 'Показывает, ожидает ли токен HS256, RS256, ES256 или другую стратегию проверки.'],
|
|
165
|
+
['Payload', 'Зарегистрированные claims и прикладные claims', 'Раскрывает идентификатор, арендатора, разрешения, роли, срок действия и несоответствия аудитории.'],
|
|
166
|
+
['Подпись', 'Криптографические байты подписи в кодировке base64url', 'Подтверждает, что сегмент подписи существует, но должен быть проверен с правильным ключом отдельно.'],
|
|
167
|
+
],
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
type: 'title',
|
|
171
|
+
text: 'Claims, которые обычно объясняют сбои аутентификации',
|
|
172
|
+
level: 3,
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
type: 'list',
|
|
176
|
+
items: [
|
|
177
|
+
'<strong>exp:</strong> если токен истёк, логика обновления или настройки часов могут быть неверными.',
|
|
178
|
+
'<strong>nbf:</strong> если токен ещё не активен, часы сервера и провайдера идентификации могут быть рассинхронизированы.',
|
|
179
|
+
'<strong>iss:</strong> если URL издателя отличается от конфигурации, токен может быть из неверного арендатора или окружения.',
|
|
180
|
+
'<strong>aud:</strong> если аудитория не совпадает с идентификатором API, токен был выпущен для другого ресурса.',
|
|
181
|
+
'<strong>alg:</strong> если алгоритм неожиданный, ваш верификатор может отклонить токен или выявить опасную ошибку конфигурации.',
|
|
182
|
+
],
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
type: 'title',
|
|
186
|
+
text: 'Сценарии использования парсера JWT при разработке',
|
|
187
|
+
level: 3,
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
type: 'comparative',
|
|
191
|
+
columns: 3,
|
|
192
|
+
items: [
|
|
193
|
+
{
|
|
194
|
+
title: 'Отладка фронтенда',
|
|
195
|
+
description: 'Проверяйте ID токены и access токены, полученные после входа, чтобы подтвердить разрешения, роли и claims профиля.',
|
|
196
|
+
icon: 'mdi:monitor-dashboard',
|
|
197
|
+
points: ['Проверка claims профиля', 'Подтверждение разрешений и ролей', 'Сравнение окружений входа'],
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
title: 'QA бэкенд API',
|
|
201
|
+
description: 'Сравнивайте ожидаемые значения издателя и аудитории с токеном, фактически отправленным в заголовке Authorization.',
|
|
202
|
+
icon: 'mdi:api',
|
|
203
|
+
highlight: true,
|
|
204
|
+
points: ['Проверка формы аудитории', 'Выявление несоответствий издателя', 'Проверка bearer токенов'],
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
title: 'Настройка провайдера идентификации',
|
|
208
|
+
description: 'Проверяйте, соответствуют ли claims от Auth0, Azure AD, Cognito, Keycloak или пользовательского провайдера ожидаемой структуре вашего приложения.',
|
|
209
|
+
icon: 'mdi:account-key',
|
|
210
|
+
points: ['Проверка данных арендатора', 'Проверка пользовательских claims', 'Сравнение сопоставлений провайдера'],
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
type: 'title',
|
|
216
|
+
text: 'Частые ошибки JWT, которые делает очевидными этот инспектор',
|
|
217
|
+
level: 3,
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
type: 'proscons',
|
|
221
|
+
title: 'Быстрые проверки против решений о доверии',
|
|
222
|
+
items: [
|
|
223
|
+
{
|
|
224
|
+
pro: 'Сразу видите некорректные токены.',
|
|
225
|
+
con: 'Он не знает вашу ожидаемую аудиторию или издателя.',
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
pro: 'Преобразует claims с Unix timestamp в читаемые даты.',
|
|
229
|
+
con: 'Он не может проверить подпись без реального ключевого материала.',
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
pro: 'Выявляет отсутствующие значения издателя, аудитории, субъекта или типа.',
|
|
233
|
+
con: 'Он не может доказать, что разрешения и роли безопасны для вашего приложения.',
|
|
234
|
+
},
|
|
235
|
+
],
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
type: 'summary',
|
|
239
|
+
title: 'Рекомендуемый рабочий процесс',
|
|
240
|
+
items: [
|
|
241
|
+
'Декодируйте токен, чтобы понять, что клиент или API фактически получили.',
|
|
242
|
+
'Проверьте exp, nbf, iss, aud, sub и alg прежде чем углубляться в логику приложения.',
|
|
243
|
+
'Проверяйте подписи и решения о доверии только в вашем слое аутентификации.',
|
|
244
|
+
'Избегайте передачи чувствительных производственных JWT в тикетах, логах или скриншотах.',
|
|
245
|
+
],
|
|
246
|
+
},
|
|
247
|
+
],
|
|
248
|
+
};
|