Привет, друзья! На днях прочитал эту интересную статью, посвященную различным вариантам хранения токена доступа (access token) на клиенте. Мое внимание привлек вариант с использованием сервис-воркера (service worker) (см. "Подход 4. Использование service worker"), поскольку я даже не задумывался о таком способе применения этого интерфейса. СВ — это посредник между клиентом и сервером (своего рода прокси-сервер), который позволяет перехватывать запросы и ответы и модифицировать их тем или иным образом. Он запускается в отдельном контексте, работает в отдельном потоке и не имеет доступа к DOM. Клиент также не имеет доступа к СВ и хранимым в нем данным. Как правило, СВ используется для обеспечения работы приложения в режиме офлайн посредством кэширования критически важных для работы приложения ресурсов. В этой статье я покажу, как реализовать простой сервис аутентификации на основе JSONWebToken и HTTP Cookie с хранением токена доступа в сервис-воркере. Для тех, кого интересует только код, вот ссылка на соответствующий репозиторий. Интересно? Тогда прошу под кат. Для локального запуска проекта необходимо выполнить следующие команды: Обратите внимание: может потребоваться выполнить миграцию с помощью команды npx prisma migrate dev --name init, а также сгенерировать клиента Prisma с помощью команды npx prisma generate. Для создания шаблона приложения использовался Yarn и Create Next App: Структура проекта: Функционал приложения является очень простым: после регистрации/авторизации пользователь получает возможность создавать/удалять задачи. Данные о пользователях и задачах хранятся в реляционной базе данных SQLite. Взаимодействие с БД осуществляется с помощью объектно-реляционного отображения Prisma. Клиент может отправлять на сервер следующие запросы: Все роуты /api/auth, кроме /api/auth/user, являются открытыми (общедоступными или публичными). Все роуты /api/todo являются закрытыми (частными или приватными). Все роуты /api/auth, кроме /api/auth/logout, возвращают данные пользователя и токен доступа. СВ перехватывает эти ответы, извлекает из тела ответа токен, записывает его в глобальную переменную и передает данные пользователя клиенту. Все роуты /api/todo требуют наличия в объекте запроса заголовка авторизации с токеном доступа — Authorization: Bearer <accessToken>. Клиент отправляет запрос без токена. СВ перехватывает запрос и добавляет в него токен из глобальной переменной. Роут /api/auth/user требует наличия куки с токеном идентификации. Куки хранится в браузере пользователя и прикрепляется к соответствующему запросу при его выполнении. Таким образом, клиент ничего не знает ни о токене доступа, который хранится в СВ, ни о токене аутентификации, который хранится в куки, доступной только серверу. Рассмотрим процесс регистрации пользователя. Процесс авторизации выглядит похожим образом (см. pages/login.tsx и pages/api/auth/login.ts). Что касается выхода пользователя из системы, то для реализации этого функционала достаточно отправить запрос на клиенте (components/Header.tsx) и удалить куки на сервере (pages/api/auth/logout.ts). Рассмотрим процесс получения данных пользователя. Получение данных пользователя и его задач реализовано с помощью кастомных хуков SWR (utils/swr.ts): Как видим, все роуты /api/auth, кроме /api/auth/logout, возвращают токен идентификации. Он не должен дойти до клиента! :) Рассмотрим процесс создания и удаления задач. Форма для создания задачи и список задач рендерятся на главной странице (pages/index.tsx). Форма выглядит следующим образом (components/CreateTodoForm.tsx): Список задач (components/TodoList.tsx): Ничего особенного. Вот как выглядит обработчик этих запросов (pages/api/todo.ts): Защита этих роутов реализована с помощью посредника utils/authGuard.ts: Как видим, для доступа к роутам /api/todo требуется наличие заголовка авторизации в объекте запроса, которого у клиента нет. Перейдем к самому интересному — СВ. Регистрируем его при запуске приложения (pages/_app.tsx): Функция регистрации СВ выглядит следующим образом (utils/registerSW.ts): Логика СВ реализована в файле public/sw.js: Как видим, СВ перехватывает две группы запросов: Пожалуй, это все, чем я хотел поделиться с вами в этой статье. Надеюсь, вы узнали что-то новое и не зря потратили время. Также надеюсь, что описанная здесь техника хранения токена доступа позволит сделать ваши приложение еще более безопасным. Благодарю за внимание и happy coding!  JavaScript Developer