ИНСТР-BASE64-JWTBase64URL · RFC 7519JWT decoderревизия 2026-05-07

Base64 для JWT токена

Декодирование JWT через Base64URL: header, payload, signature. Чем Base64URL отличается от классического Base64.

⏱ работает в браузере · без регистрации
Инструмент · ИНСТР-BASE64-JWT|real-time
calcal.ru / base64-dlya-jwt-tokena-decoder
Загрузка...
3
Части JWT
Base64URL
Кодирование
JSON
Формат claims
0
Запросов к серверу

JWT и Base64

JWT (JSON Web Token) — самый популярный формат для авторизации в современных API. RFC 7519, разработан в 2015. Состоит из трёх частей через точку: header.payload.signature. Каждая часть — это JSON, закодированный в специальном варианте Base64 — Base64URL.

Пример JWT:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTEyMyIsIm5hbWUiOiJJdmFuIiwiZXhwIjoxNzM1Njg5NjAwfQ.HpAFxOHr3l5ZcZD9yLzxs1F7Q8Vk0zUBzKqDZE6KQ-w

Видны три части через точку. Декодируем каждую через Base64:

Header   = {"alg":"HS256","typ":"JWT"}
Payload  = {"sub":"user-123","name":"Ivan","exp":1735689600}
Signature = HMAC-SHA256(header.payload, secret_key)

Base64URL vs обычный Base64

Обычный Base64 использует 64 символа: A-Z, a-z, 0-9, +, /. Знак + и / небезопасны в URL — их нужно URL-encoding (%2B, %2F). Это удваивает длину и усложняет работу. Base64URL решает проблему:

СимволBase64Base64URL
A-Z, a-z, 0-9✓ те же✓ те же
62-й+-
63-й/_
Padding= (всегда)= (необязательно)

Чтобы декодировать Base64URL обычным Base64-декодером:

  1. Заменить - на +.
  2. Заменить _ на /.
  3. Добавить padding = до длины кратной 4.
JWT uses the URL-safe variant of Base64 (Base64URL). The padding character '=' is removed. The header and payload are JSON objects that are Base64URL-encoded, then concatenated with a period separator.RFC 7519 — JSON Web Token (JWT), section 3.1

3 части токена

Header

Описывает тип токена и алгоритм подписи:

{
  "alg": "HS256",   // HMAC-SHA-256
  "typ": "JWT",     // тип токена
  "kid": "key-1"    // key ID (опционально, для key rotation)
}

Алгоритмы:

  • HS256, HS384, HS512 — HMAC + SHA-2. Симметричный ключ.
  • RS256, RS384, RS512 — RSA + SHA-2. Асимметричный (publickey.privatekey).
  • ES256, ES384, ES512 — ECDSA + SHA-2. Асимметричный, более компактный.
  • PS256 — RSA-PSS + SHA-256. Современная замена RS256.
  • none — без подписи. НИКОГДА не используйте в production.

Payload (claims)

{
  // Стандартные claims (RFC 7519)
  "iss": "https://api.example.com",  // issuer
  "sub": "user-123",                  // subject (user ID)
  "aud": "mobile-app",                // audience
  "exp": 1735689600,                  // expiration (Unix timestamp)
  "iat": 1735603200,                  // issued at
  "nbf": 1735603200,                  // not before
  "jti": "abc-123-def-456",          // JWT ID

  // Кастомные claims
  "name": "Иван Петров",
  "email": "ivan@example.com",
  "roles": ["admin", "user"],
  "permissions": ["read:users", "write:orders"]
}

Payload — ОТКРЫТЫЙ текст (после Base64URL декодирования). Не храните в нём пароли, секретные ключи, токены доступа к третьим API.

Signature

Подпись = функция от header + payload + secret key. Обеспечивает целостность токена. Если кто-то изменит payload, signature не совпадёт.

// HS256 (HMAC-SHA256)
signature = HMAC-SHA256(
  base64url(header) + '.' + base64url(payload),
  secret_key
);

// RS256 (RSA-SHA256)
signature = RSA_SIGN(
  SHA256(base64url(header) + '.' + base64url(payload)),
  private_key
);

Декодирование в коде

JavaScript (без проверки подписи)

function decodeJwt(token) {
  const [headerB64, payloadB64, signatureB64] = token.split('.');

  // Base64URL → Base64
  const toBase64 = (s) => s.replace(/-/g, '+').replace(/_/g, '/');

  return {
    header: JSON.parse(atob(toBase64(headerB64))),
    payload: JSON.parse(atob(toBase64(payloadB64))),
    signature: signatureB64,
  };
}

// Использование
const decoded = decodeJwt(token);
console.log(decoded.payload.sub); // user-123
console.log(new Date(decoded.payload.exp * 1000)); // expiration date

// Проверка истечения
const now = Math.floor(Date.now() / 1000);
if (decoded.payload.exp < now) {
  console.log('Token expired!');
}

JavaScript (с проверкой подписи через jose)

import { jwtVerify } from 'jose';

const secret = new TextEncoder().encode(process.env.JWT_SECRET);

try {
  const { payload } = await jwtVerify(token, secret, {
    issuer: 'https://api.example.com',
    audience: 'mobile-app',
  });
  console.log('Valid token:', payload);
} catch (e) {
  console.log('Invalid token:', e.message);
}

Python

import jwt
import base64
import json

# Без проверки подписи (только декодирование)
def decode_jwt_unsafe(token):
    header_b64, payload_b64, signature_b64 = token.split('.')
    # Add padding
    payload_b64 += '=' * (4 - len(payload_b64) % 4)
    payload_bytes = base64.urlsafe_b64decode(payload_b64)
    return json.loads(payload_bytes)

# С проверкой подписи (PyJWT)
def decode_jwt_safe(token, secret):
    return jwt.decode(token, secret, algorithms=["HS256"])

# Использование
payload = decode_jwt_unsafe(token)  # для отладки
payload = decode_jwt_safe(token, secret)  # для production

Безопасность

  • Не храните секреты в payload. Любой может декодировать. Только идентификаторы и метаданные.
  • Короткий exp. Access token — 15-30 минут. Refresh token — 7-30 дней. Балансирует UX и безопасность.
  • Проверяйте exp на сервере. Хотя клиент должен проверять для UX, сервер ОБЯЗАН проверять.
  • HTTPS обязателен. JWT в HTTP — токен виден в логах прокси, истории браузера. Только HTTPS.
  • Не разрешайте none алгоритм. Жёстко задайте список allowed algorithms в verify.
  • Не используйте JWT для сессий с возможностью отзыва. Refresh token + блэклист или опаковский session ID.
  • HTTPOnly cookie для refresh. Защита от XSS. Access token может быть в memory.
ИСТОЧНИКИ
  1. RFC 7519 — JSON Web Token (JWT). IETF. datatracker.ietf.org/doc/html/rfc7519. 2015.
  2. RFC 7515 — JSON Web Signature (JWS). IETF. datatracker.ietf.org/doc/html/rfc7515. 2015.
  3. JWT Best Practices — OWASP. OWASP. owasp.org/www-chapter-vancouver/assets/presentations/2020-01_Attacking_and_Securing_JWT.pdf. 2020.
ЧАСТЫЕ ВОПРОСЫ

Часто задаваемые вопросы

JWT (JSON Web Token) — стандарт безопасной передачи данных в виде подписанного токена. Состоит из 3 частей через точку: header.payload.signature. Каждая часть — это JSON, закодированный в Base64URL. Поэтому JWT можно «расшифровать» (декодировать) обычным Base64 декодером — и увидеть содержимое. Это НЕ обход безопасности — JWT не зашифрован, он подписан. Любой может прочитать payload, но изменить (без знания ключа) — нет.
Обычный Base64 использует символы +, /, = — они НЕ безопасны в URL (нужно URL-encoding). Base64URL заменяет: + → -, / → _, = (padding) обычно убирается. Это позволяет JWT передавать в URL как query параметр без дополнительного кодирования. Альфавит Base64URL: A-Z, a-z, 0-9, -, _ (64 символа = 6 бит на символ). Декодирование — то же что обычный Base64, но сначала восстановить +, / из -, _.
<strong>Header</strong>: алгоритм подписи и тип токена. Например: <code>{"alg":"HS256","typ":"JWT"}</code>. <strong>Payload</strong>: claims (заявления) — данные пользователя, время истечения, права. Например: <code>{"sub":"user-123","name":"Иван","exp":1735689600}</code>. <strong>Signature</strong>: HMAC от header.payload с использованием секретного ключа. Подтверждает что токен не подделан.
JWT ПОДПИСАН, не зашифрован. Это значит: (1) Любой может прочитать payload — это НЕ секрет. Не храните пароли или ключи в payload. (2) Любая попытка изменить payload — приводит к невалидной signature, сервер отвергает. (3) Если нужна шифрование (скрыть содержимое) — используйте JWE (JSON Web Encryption). На практике 99% JWT — это JWS (signed). JWE используется реже, для специфичных случаев.
Стандартные (RFC 7519): <code>iss</code> (issuer — кто выпустил), <code>sub</code> (subject — кому), <code>aud</code> (audience — для какой системы), <code>exp</code> (expiration time — Unix timestamp), <code>nbf</code> (not before — действителен с), <code>iat</code> (issued at — выпущен), <code>jti</code> (JWT ID — уникальный). Кастомные: <code>name</code>, <code>email</code>, <code>roles</code>, <code>permissions</code>. Не кладите PII (паспортные данные, СНИЛС) — токен может попасть в логи.
JavaScript: <code>const [, payload] = token.split(".");\nconst data = JSON.parse(atob(payload.replace(/-/g, "+").replace(/_/g, "/")));</code>. Python: <code>import jwt; jwt.decode(token, options={"verify_signature": False})</code> — без проверки подписи. С проверкой — нужен секретный ключ: <code>jwt.decode(token, "secret", algorithms=["HS256"])</code>. Без проверки — просто декодирование Base64URL. С проверкой — также вычисление HMAC и сравнение.
Это известная атака. Раньше многие JWT-библиотеки принимали алгоритм «none» — токен без подписи. Атакующий менял header на <code>{"alg":"none"}</code>, удалял signature — и сервер принимал. Современные библиотеки требуют явное указание алгоритма при verify. Никогда не доверяйте полю alg из header — задайте список разрешённых алгоритмов на сервере. Никогда не разрешайте «none» в production.
Cookies (sessionId на сервере) — традиционный подход. Stateful (сервер хранит сессии). Хорошо: можно отозвать. Плохо: горизонтальное масштабирование сложнее. JWT — stateless. Хорошо: масштабирование без БД, microservices. Плохо: невозможно отозвать (только ждать exp). На практике: используйте JWT для access token (короткий exp, 15 мин) + refresh token в HTTPOnly cookie. Так и stateless и можно отзывать.
Лиана Арифметова
АВТОРverifiedред. calcal.ru

Лиана Арифметова

Создатель и главный редактор

Миссия: демократизировать сложные расчёты. Превратить страх перед числами в ясность и контроль. Девиз: «Любая повторяющаяся задача заслуживает своего калькулятора».

Mathematical Engineering · МФТИ · редактирует каталог с 2012 года

Был ли этот калькулятор полезен?

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ

Инструмент справочный — не заменяет эксперта

Только для информационных целей. Все расчёты, результаты и данные, предоставляемые инструментом, носят исключительно ознакомительный и справочный характер. Они не являются профессиональной консультацией — медицинской, юридической, финансовой, инженерной или иной.

Точность результатов. Калькулятор основан на общепринятых формулах и методиках, однако фактические результаты могут отличаться в зависимости от индивидуальных условий, исходных данных и применяемых стандартов. Мы не гарантируем полноту, точность или актуальность приведённых расчётов.

Профессиональные решения — медицинские, финансовые, инженерные — должны приниматься только после консультации с квалифицированным специалистом. Не используйте автоматический расчёт как единственное основание для важных решений.

Ограничение ответственности. Авторы и разработчики сервиса не несут ответственности за прямой или косвенный ущерб, возникший из-за использования данных расчётов. Пользователь принимает на себя всю ответственность за интерпретацию результатов.