← Назад к вопросам

Где хранится JWT токен?

1.8 Middle🔥 201 комментариев
#API тестирование#Архитектура приложений

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Хранение JWT токена: подходы, безопасность и лучшие практики

Веб-приложения используют JSON Web Token (JWT) для аутентификации и передачи данных между сторонами. Место хранения токена на клиентской стороне — критически важный архитектурный выбор, влияющий на безопасность и удобство пользователя. Вот основные подходы, их плюсы, минусы и рекомендации.

Основные места хранения на клиенте

1. LocalStorage (или SessionStorage)

Наиболее распространённый, но спорный с точки зрения безопасности метод.

// Пример сохранения токена в localStorage после успешного логина
const login = async (credentials) => {
    const response = await fetch('/api/login', {
        method: 'POST',
        body: JSON.stringify(credentials)
    });
    const data = await response.json();
    if (data.token) {
        localStorage.setItem('jwt_token', data.token); // Сохранение
    }
};

// Пример использования токена из localStorage для авторизованного запроса
const fetchData = async () => {
    const token = localStorage.getItem('jwt_token');
    const response = await fetch('/api/protected', {
        headers: {
            'Authorization': `Bearer ${token}`
        }
    });
    return response.json();
};
  • Преимущества: Простота реализации, токен доступен во всех вкладках/окнах одного источника (origin).
  • Недостатки: Уязвим к XSS-атакам (Cross-Site Scripting). Зловредный JavaScript, внедрённый на страницу, может получить токен из хранилища.

2. HttpOnly Cookies

Более безопасный метод, рекомендованный OWASP для защиты от XSS.

// Бэкенд (Node.js/Express пример) устанавливает токен в HttpOnly куку
app.post('/login', (req, res) => {
    // ... проверка логина и пароля
    const token = generateJwt(user);
    res.cookie('jwt_token', token, {
        httpOnly: true,  // Ключевая настройка! Cookie недоступна из JavaScript
        secure: true,    // Передача только по HTTPS (обязательно в продакшене)
        sameSite: 'strict' // Защита от CSRF-атак
    });
    res.json({ message: 'Успешный вход' });
});

// Фронтенду не нужно вручную прикреплять токен к запросам.
// Браузер автоматически отправляет куку с каждым запросом на домен.
  • Преимущества: Недоступность токена для JavaScript делает его неуязвимым к большинству XSS-атак.
  • Недостатки: Требует настройки CORS (Cross-Origin Resource Sharing) и защиты от CSRF-атак (используя sameSite флаги и/или CSRF-токены). Токен автоматически отправляется со всеми запросами к домену, что может упростить некоторые атаки, если кука не настроена корректно.

3. In-memory (или "Без сохранения")

Токен хранится только в оперативной памяти JavaScript (например, в замыкании или переменной состояния фреймворка типа React/Vue).

// Пример с использованием React Context/State
import React, { useState, createContext, useContext } from 'react';

const AuthContext = createContext(null);

export const AuthProvider = ({ children }) => {
    const [token, setToken] = useState(null); // Токен живет только в состоянии компонента

    const login = (newToken) => setToken(newToken);
    const logout = () => setToken(null);

    return (
        <AuthContext.Provider value={{ token, login, logout }}>
            {children}
        </AuthContext.Provider>
    );
};

// Использование токена для запроса
const useApi = () => {
    const { token } = useContext(AuthContext);
    const call = (url) => fetch(url, {
        headers: { 'Authorization': `Bearer ${token}` }
    });
    return { call };
};
  • Преимущества: Максимальная безопасность. Токен полностью исчезает при закрытии вкладки браузера, недоступен для XSS после перезагрузки страницы.
  • Недостатки: Пользователь вынужден логиниться заново при каждой перезагрузке страницы или открытии новой вкладки. Не подходит для долгоживущих сессий.

4. Refresh Token + Access Token в Secure Storage

Продвинутый и самый безопасный паттерн, особенно для SPA (Single Page Applications).

  • Короткоживущий Access Token (JWT) хранится в памяти приложения.
  • Долгоживущий Refresh Token хранится в HttpOnly, Secure, SameSite куке (или в безопасном серверном хранилище сессий).
// Схематичный пример работы:
// 1. Логин: сервер возвращает Access Token (в теле ответа) и устанавливает Refresh Token в HttpOnly куку.
// 2. Клиент использует Access Token для API-запросов.
// 3. При истечении срока Access Token (получена 401 ошибка), клиент делает специальный запрос к `/refresh` endpoint.
// 4. Браузер автоматически отправляет Refresh Token (куку) на этот endpoint.
// 5. Сервер валидирует Refresh Token и выдает новый Access Token.

// Фронтенд: перехват 401 ошибки и попытка обновить токен
let refreshTokenRequest = null;
async function refreshAuthToken() {
    if (!refreshTokenRequest) {
        // Запрос на обновление. Refresh Token отправится автоматически в куках.
        refreshTokenRequest = fetch('/api/auth/refresh', { method: 'POST' })
            .then(res => res.json())
            .then(data => {
                refreshTokenRequest = null;
                return data.accessToken; // Новый короткоживущий токен
            });
    }
    return refreshTokenRequest;
}

Выводы и рекомендации

Выбор стратегии зависит от требований приложения к безопасности и UX:

  • Для максимальной безопасности (банковские приложения, админ-панели): используйте связку Refresh Token в HttpOnly Cookie + короткоживущий Access Token в памяти. Это баланс безопасности (защита от XSS и CSRF) и удобства (пользователь остается в системе).
  • Для стандартных веб-приложений: HttpOnly Cookie с правильно настроенными флагами (Secure, SameSite=Strict/Lax) и защитой от CSRF — надежный и распространённый выбор.
  • LocalStorage/SessionStorage стоит использовать только для токенов, не содержащих критичных данных, в защищённых от XSS приложениях, либо для внутренних инструментов. Всегда помните о рисках.
  • Чистая In-memory стратегия подходит для приложений с высочайшими требованиями к безопасности, где выход из системы при закрытии вкладки является приемлемым сценарием.

Итог: Не существует единственно правильного ответа. HttpOnly Cookie сегодня считается best practice для большинства сценариев, но архитектура Refresh + Access Token обеспечивает более тонкий контроль и повышенную безопасность, особенно в современных SPA и нативных мобильных приложениях.

Где хранится JWT токен? | PrepBro