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

Где можно хранить JWT?

2.0 Middle🔥 153 комментариев
#Аутентификация и безопасность

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

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

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

Места хранения JWT: сравнение подходов

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

1. LocalStorage / SessionStorage (Web Storage API)

Наиболее простое решение для SPA (Single Page Applications) на клиенте.

// Сохранение токена после успешной аутентификации
const saveToken = (token) => {
    localStorage.setItem('access_token', token);
    // или sessionStorage.setItem('access_token', token);
};

// Извлечение токена для использования в запросах
const getToken = () => {
    return localStorage.getItem('access_token');
};

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

  • Простота реализации
  • Токен автоматически не отправляется на другие домены
  • Доступен всем вкладкам одного origin (для localStorage)

Недостатки:

  • Уязвимость к XSS-атакам: злонамеренный скрипт может получить доступ к хранилищу
  • Нет встроенного механизма обновления токена
  • Требуется ручное управление сроком жизни

2. HTTP-Only Cookies

Более безопасный подход, при котором JavaScript не имеет прямого доступа к токену.

// Пример установки JWT в cookie на сервере (C# ASP.NET Core)
public IActionResult Login(UserCredentials credentials)
{
    // Аутентификация пользователя...
    var token = GenerateJwtToken(credentials);
    
    Response.Cookies.Append("access_token", token, new CookieOptions
    {
        HttpOnly = true,     // JavaScript не может прочитать
        Secure = true,       // Только по HTTPS
        SameSite = SameSiteMode.Strict, // Защита от CSRF
        Expires = DateTime.UtcNow.AddMinutes(15)
    });
    
    return Ok(new { message = "Authenticated successfully" });
}

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

  • Защита от XSS: JavaScript не имеет доступа к cookie
  • Автоматическая отправка с каждым запросом
  • Встроенные механизмы безопасности (Secure, HttpOnly, SameSite)

Недостатки:

  • Уязвимость к CSRF-атакам (хотя SameSite cookie и CORS политики помогают)
  • Сложнее реализовать обновление токена без JavaScript
  • Токен отправляется даже на статические ресурсы

3. In-Memory (JavaScript переменная)

Хранение токена только в оперативной памяти приложения.

let authToken = null;

class AuthService {
    setToken(token) {
        authToken = token;
        // НЕ сохраняем в localStorage/cookie
    }
    
    getToken() {
        return authToken;
    }
    
    // Токен исчезает при обновлении страницы
}

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

  • Максимальная безопасность от XSS (токен недоступен через Storage API)
  • Токен автоматически очищается при закрытии вкладки

Недостатки:

  • Пользователь должен повторно логиниться после каждого обновления страницы
  • Не работает для нескольких вкладок приложения
  • Плохой пользовательский опыт

4. React Context / Vuex / State Management

Использование стейт-менеджеров современных фреймворков в сочетании с другими методами.

// React Context пример
const AuthContext = createContext();

const AuthProvider = ({ children }) => {
    const [token, setToken] = useState(() => {
        // Инициализация из безопасного источника
        return localStorage.getItem('access_token');
    });
    
    // ...логика обновления, проверки срока действия
    
    return (
        <AuthContext.Provider value={{ token, setToken }}>
            {children}
        </AuthContext.Provider>
    );
};

5. Secure Storage на мобильных устройствах

Для мобильных приложений используются специальные API:

  • iOS: Keychain Services
  • Android: Keystore System
  • Кроссплатформенные решения: React Native Keychain, Flutter Secure Storage

Рекомендации по выбору стратегии

Для веб-приложений (SPA):

  1. Предпочтительный подход: Refresh Token в HttpOnly cookie + Access Token в памяти. Это обеспечивает баланс безопасности и UX:
    *   Access Token живет недолго (15-30 минут) и хранится в памяти
    *   Refresh Token живет дольше (неделя/месяц) и хранится в HttpOnly cookie
    *   При истечении Access Token, приложение использует Refresh Token для получения нового

  1. Архитектура с Backend-for-Frontend: выделенный BFF слой, который хранит все токены и выступает прокси между SPA и API.

Пример реализации на C#:

// Контроллер для обновления токена
[ApiController]
[Route("api/auth")]
public class AuthController : ControllerBase
{
    [HttpPost("refresh")]
    public async Task<IActionResult> RefreshToken()
    {
        // Извлекаем refresh token из HttpOnly cookie
        var refreshToken = Request.Cookies["refresh_token"];
        
        if (string.IsNullOrEmpty(refreshToken))
            return Unauthorized();
        
        // Валидируем refresh token
        var principal = ValidateRefreshToken(refreshToken);
        
        if (principal == null)
            return Unauthorized();
        
        // Генерируем новую пару токенов
        var newAccessToken = GenerateAccessToken(principal);
        var newRefreshToken = GenerateRefreshToken(principal);
        
        // Устанавливаем refresh token в cookie
        Response.Cookies.Append("refresh_token", newRefreshToken, new CookieOptions
        {
            HttpOnly = true,
            Secure = true,
            SameSite = SameSiteMode.Strict,
            Expires = DateTime.UtcNow.AddDays(7)
        });
        
        // Возвращаем access token в теле ответа
        return Ok(new { accessToken = newAccessToken });
    }
}

Для мобильных/нативных приложений:

  • Используйте безопасное хранилище устройства
  • Реализуйте механизм автоматического обновления токенов
  • Используйте Proof Key for Code Exchange (PKCE) для OAuth

Ключевые принципы безопасности:

  1. Никогда не храните чувствительные данные в JWT payload - токены могут быть прочитаны
  2. Используйте короткое время жизни Access Token (минуты, а не часы)
  3. Реализуйте механизм отзыва токенов через blacklist или использование короткоживущих токенов
  4. Всегда используйте HTTPS в production
  5. Регулярно обновляйте секретные ключи подписи JWT

Выбор места хранения зависит от типа приложения, требований безопасности и пользовательского опыта. Современные best practices склоняются к гибридному подходу с разделением Access и Refresh токенов и использованием разных механизмов хранения для каждого.