Что такое токен и зачем он нужен
HTTP не хранит состояние: сервер не знает, кто вы, при каждом запросе. После входа сервер выдаёт доказательство (токен), а клиент прикладывает его к каждому запросу: Authorization: Bearer <token>. Есть две основные модели: серверная сессия (токен — лишь ключ, состояние на сервере) и самопроверяемый токен, например JWT.
JWT состоит из трёх частей: header.payload.signature. Каждая часть — JSON в base64url (кроме подписи). В заголовке алгоритм (alg), в нагрузке утверждения (sub, exp, iat, iss, aud). Подпись — это header.payload, подписанные секретным (HS256) или приватным ключом (RS256, ES256).
⚠️ JWT не зашифрован, а подписан: нагрузку может прочитать любой. Не кладите туда пароли, номера карт и другие чувствительные данные.
Чтение JWT на клиенте
Клиент подпись не проверяет (ключа у него нет), но из нагрузки может прочитать полезное: имя, роль (для интерфейса), exp (когда пора обновлять). Base64url отличается от обычного base64 символами -, _ и отсутствием =. Для UTF-8 результат atob декодируйте через TextDecoder.
const token =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.' +
'eyJzdWIiOiI0MiIsIm5hbWUiOiJBeXNlbCIsInJvbGUiOiJlZGl0b3IiLCJpYXQiOjE3MDAwMDAwMDAsImV4cCI6MTkwMDAwMDAwMH0.' +
'c2lnbmF0dXJl';
function decodePart(part) {
const base64 = part.replace(/-/g, '+').replace(/_/g, '/');
const bytes = Uint8Array.from(atob(base64), (ch) => ch.charCodeAt(0));
return JSON.parse(new TextDecoder().decode(bytes));
}
function decodeJwt(jwt) {
const [header, payload] = jwt.split('.');
return { header: decodePart(header), payload: decodePart(payload) };
}
function isExpired(payload, now = Date.now()) {
return payload.exp * 1000 <= now;
}
const { header, payload } = decodeJwt(token);
console.log(header.alg, payload.sub, payload.role);
console.log('expired in 2026:', isExpired(payload, Date.UTC(2026, 0, 1)));
console.log('expired in 2031:', isExpired(payload, Date.UTC(2031, 0, 1)));Результат:
HS256 42 editor
expired in 2026: false
expired in 2031: true