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

Где хранить токены в браузере для скрытия?

2.0 Middle🔥 161 комментариев
#API и веб-протоколы#Безопасность

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

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

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

Безопасное хранение токенов в браузере: сравнительный анализ

В современных веб-приложениях токены аутентификации (JWT, access/refresh токены) требуют особого подхода к хранению на клиенте. Полное "скрытие" невозможно, но можно минимизировать риски, используя правильные браузерные API. Вот основные подходы в порядке увеличения безопасности:

Ненадёжные методы (не рекомендуются)

// ❌ ОПАСНО: LocalStorage/SessionStorage
localStorage.setItem('token', 'your_jwt_token');
// Уязвимо к XSS-атакам: любой JS-код на странице имеет доступ
// ❌ ОПАСНО: Cookie без флагов безопасности
document.cookie = "token=your_jwt_token";
// Доступно через document.cookie, уязвимо к XSS

Рекомендуемые подходы

1. HTTP-Only Cookies (базовый уровень защиты)

// Сервер устанавливает cookie с флагами
Set-Cookie: token=your_jwt_token; HttpOnly; Secure; SameSite=Strict

Преимущества:

  • Недоступны JavaScript через document.cookie
  • Защита от XSS-атак (но не от CSRF)
  • Автоматическая отправка с каждым запросом

Ограничения:

  • Уязвимость к CSRF-атакам (требует дополнительной защиты)
  • Сложнее управлять на клиенте (только через HTTP-запросы)
  • Ограничения по доменам

2. Secure Cookies с дополнительной защитой от CSRF

// Двойная cookie-техника для защиты от CSRF
Set-Cookie: token=your_jwt_token; HttpOnly; Secure; SameSite=Strict
Set-Cookie: csrf_token=random_value; Secure; SameSite=Lax

// Клиент отправляет CSRF-токен в заголовке
fetch('/api/data', {
    headers: {
        'X-CSRF-Token': getCookie('csrf_token')
    }
});

3. Refresh Token Rotation с безопасным хранением

// Стратегия разделения токенов:
// - Короткоживущий access token в памяти
// - Долгоживущий refresh token в HttpOnly cookie

// В памяти приложения (исчезает при закрытии вкладки)
let accessToken = null;

async function refreshAccessToken() {
    const response = await fetch('/auth/refresh', {
        method: 'POST',
        credentials: 'include' // Отправляет HttpOnly refresh token
    });
    const data = await response.json();
    accessToken = data.access_token; // Хранится только в памяти
}

Современный подход: Secure Context и Credential Management API

4. Credentials Management API (современные браузеры)

// Более безопасная альтернатива
navigator.credentials.store({
    password: {
        id: 'user_token',
        password: 'encrypted_token_data'
    }
});

// Получение токена
navigator.credentials.get({password: true})
    .then(cred => {
        // Использование токена
    });

5. Session Storage для временных токенов

// ✅ Ограниченное использование для access tokens
// Только если защищены от XSS и нужен контроль со стороны JS
sessionStorage.setItem('access_token', encryptedToken);

// Преимущество: очищается автоматически при закрытии вкладки
// Но всё ещё уязвимо к XSS, если приложение скомпрометировано

Рекомендуемая архитектура

  1. Access Token: хранить в оперативной памяти приложения, обновлять через silent authentication
  2. Refresh Token: хранить в HttpOnly, Secure, SameSite=Strict cookie
  3. CSRF Protection: использовать токены/заголовки для дополнительной защиты
// Пример защищённой реализации
class TokenManager {
    constructor() {
        this.accessToken = null;
    }
    
    async initialize() {
        // Попытка получить access token через refresh token
        try {
            const response = await fetch('/auth/refresh', {
                method: 'POST',
                credentials: 'include',
                headers: {'X-Requested-With': 'XMLHttpRequest'}
            });
            
            if (response.ok) {
                const data = await response.json();
                this.accessToken = data.access_token;
                // Устанавливаем таймер для автоматического обновления
                setTimeout(() => this.refresh(), data.expires_in * 1000 - 60000);
            }
        } catch (error) {
            this.logout();
        }
    }
    
    getAuthHeader() {
        return this.accessToken ? {'Authorization': `Bearer ${this.accessToken}`} : {};
    }
}

Дополнительные меры безопасности

  • Content Security Policy (CSP): ограничение источников скриптов
  • Subresource Integrity (SRI): проверка целостности сторонних скриптов
  • Регулярная ротация токенов: уменьшение времени жизни access token
  • Инспекция заголовков: защита от утечек через Referer

Критические выводы

  1. Абсолютной защиты не существует — речь идёт о минимизации рисков
  2. HttpOnly cookies — золотой стандарт для refresh token
  3. Оперативная память — наиболее безопасное место для access token
  4. Защита от XSS приоритетнее выбора метода хранения токенов
  5. Современные браузерные API предоставляют дополнительные возможности

Выбор метода зависит от требований приложения: SPA с отдельным API требуют одного подхода, традиционные MVC-приложения — другого. Важнее всего обеспечить комплексную защиту, а не полагаться на один метод хранения.

Где хранить токены в браузере для скрытия? | PrepBro