Comments 20

Нет, ну серьезно?


Используя локальное хранилище, удобно работать с API, которые требуют размещать токен доступа в заголовок запроса. Например — так: Authorization Bearer ${access_token}.

Если у вас API требует access_token, то это не "удобно" или "не удобно", это единственный вариант.


Главное преимущество куки-файлов заключается в том, что они недоступны из JavaScript

Куки, в общем случае, прекрасно доступны для JavaScript. Недоступны они в двух случаях — если стоит флаг httpOnly или они принадлежат чужому домену.


Если вы используете флаг HttpOnly и защищённые куки-файлы.

Это какие такие защищенные куки? Наверное, имеются ввиду Secure флаг, который запрещает передачу куков при http запросе. Но secure флаг никак не защищает куки от доступа к ним с помощью JS.


CSRF-атаки — это атаки, в ходе которых пользователя каким-то образом принуждают к выполнению особого запроса

Никто никого не принуждает. СSRF это подделка/эмуляция запроса от имени пользователя. Если речь идет о принуждении, то уже никакие техники защиты не помогут.


Возможно Вам стоит найти человека, который разбирается в этой теме?

Если у вас API требует access_token, то это не "удобно" или "не удобно", это единственный вариант.

Или получать его из сервиса аутентикации при каждой загрузке страницы и хранить в памяти. В принципе, это более широкая трактовка того, что в статье названо "хранение токенов обновления в HttpOnly-куки, а токенов доступа — в памяти"


Наверное, имеются ввиду Secure флаг

Именно так. В оригинале secure выделено как ключевое слово, наравне с httpOnly. Переводчик не осилил.


Но secure флаг никак не защищает куки от доступа к ним с помощью JS.

А тут уже претензия не к переводу, а к автору оригинала. Зачем он приплел сюда secure — непонятно.


пользователя каким-то образом принуждают

Очередная кривая формулировка автора оригинала. Кто в курсе, тот поймет (но ему это объяснение и не нужно), а кто не курсе, того такое описание только запутает.

Итоги: И статья такая себе, и переводчик "не помогает". И зачем?

Это какие такие защищенные куки? Наверное, имеются ввиду Secure флаг, который запрещает передачу куков при http запросе. Но secure флаг никак не защищает куки от доступа к ним с помощью JS.

Полагаю, имеется в виду как раз флаг HttpOnly.
Я бы вообще начал с вопроса:
«А зачем нужен JWT если раньше обходились session id / токен?»

И если кратко то JWT, это шифрованный user profile, который передают через клиента, и нужен он для:
(а) кластеризации за лоад-балансером, и (б) авторизации, без обращения к база/сервису на каждый запрос пользователя.

Статья не то чтобы не раскрывает тему, она больше вводит в заблуждение...


Существуют сценарии, при реализации которых вы не можете передавать куки своему API-серверу.

А потом складываем refresh token в куки… выходит от недостатка не избавились...


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


Для меня тоже долгое время было большой загадкой, а где таки хранить токены. После некоторого погружения в бекенд моя картина мира складывается в вариант, когда мы выносим сервис авторизации в отдельный сервис (на отдельном домене), с которым у нас есть нормальная куки сессия, хранящаяся на бекенде в базе и т.д. и т.п., от этого сервиса мы получаем токены, храним их в оперативной памяти и уже с ними ходим в остальные сервисы.


Причем нигде не должно быть возни с CORS, клиент всегда шлет на родной домен запросы, которые проверяются одним api gateway'ем, а потом раскидываются по сервисам.


Еще одной замечательной особенностью токенов является их независимость от браузерных особенностей работы с куками, что позволяет использовать их между серверами и с мобильных устройств, что также упущено в этой статье.


Я верю, что мой коммент будет полезен тем, кто начинает читать статьи с комментариев =)

Это те же яйца вид сбоку. Токен от сервиса авторизации в итоге нужно положить либо в куку, либо в local storage и огрести то, о чем в статье пишут.

В описанном мной примере хранить не нужно, так как мы можем сходить к серверу авторизации за новыми токенами при перезагрузки страницы. Для того, чтобы это сделать нам нужна сессия на сервере авторизации, это скорее всего будет что-то в httpOnly куках, но это не будут те же токены, которые мы будем использовать на других сервисах.


Мне на самом деле интересны проблемы, которые тут можно огрести, и которые я пока не вижу,… но я их пока не вижу =)

Безусловно полезен.
Я просто пришел к аналогичному выводу, и вы его подтвердили. Совершенно непонятно, какой смысл хранить оба токена в одной куке, и, получается передавать их с запросами. Смысл рефреша теряется, он все равно ходит парой с токеном доступа. Важным аспектом то было то, чтобы отправлять рефреш только когда нужен рефреш… В общем, идея с отдельным доменом эту проблему как раз и решает. Отнимаем доступ у приложения к кукам с помощью httponly и получаем отдельно куку для доступа и отдельно куку для рефреша.

ктонибудь организовывал через токены доступ к видео? чтобы их с помощью софта не скачивали

И софту будет достаточно проставить тем же образом токены в заголовках. Смысл? Разве что защита от тупого "вставить ссылку в поле браузера".

Размер куки-файлов ограничен 4 Кб. Поэтому, если вы используете большие JWT, хранение их в куки-файлах вам не подойдёт.

Сейчас бы отправлять 4кб в каждом запросе.

Вы опоздали лет на 10 с таким заявлением. Сейчас запросов по количеству явно больше, и в каждом вполне себе будет миллион utm- меток, которые с лёгкостью нагребут на больше чем 4кб запроса ..

Локальное хранилище уязвимо к XSS-атакам

Почему всегда доступ из js в localStorage объявляют как минус? Ведь если на сайт УЖЕ прошла xss атака, т.е внедрили чужой js… то уже как бы поздно. Какая уже разница где хранятся токены. Наворотить уже можно что угодно по идее.
Т.е. в контексте вопроса в статье, переживать необходимо про xss, а не о том где бы безопаснее токены хранить.

Про это и упомянули:


при такой схеме работы злоумышленнику может быть выгоднее атаковать сервер, пользуясь компьютером жертвы, а не собственным.

Действительно, если ты нашел XSS, то тебя ничего не остановит.

Тут идёт речь про усложнение атаки. Даже если нашли XSS, чтобы с ним что-то сделать недостаточно будет просто слить куки. Не стоит строить безопасность с одним «фронтом».
Cookie и localStorage в контексте заголовка отличаются лишь степенью доступности.
Если куки прочитать нельзя (выставив флаг HttpOnly), то зачем их сравнивать?

Содержимое статьи можно уложить в три предложения — храним сессию в куках с флагами secure, HttpOnly и SameSite. Выставляем заголовки X-Content-Type-Options, Strict-Transport-Security, X-XSS-Protection, X-Frame-Options, Referrer-Policy, Content-Security-Policy, Expect-CT, Feature-Policy и Cache-Control. Ну и не забываем про токен.

Так то refresh token’ы нельзя выдавать в браузер. В случае использования OpenID Connect была возможность так называемого «silent renew», но судя по блогу разработчиков вебкита, она уже канула в лету (для Safari — в последних Technology Preview, для Chrome — в 2022) https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/
В драфтах OAuth 2.1 implicit flow выпилили, остались только только authorization code с pkce для public/confidential клиентов и client credentials flow. Соответственно единственный вариант для больших SPA, которые разрабатываются сейчас, с заделом на долгую и счастливую поддержку, которым от провайдера нужно чуть побольше, чем просто аутентификация — это code + pkce и httponly secure куки, к которым имеет доступ только BFF.

Исчерпывающее объяснение работы с JWT:
https://gist.github.com/zmts/802dc9c3510d79fd40f9dc38a12bccfc
Only those users with full accounts are able to leave comments. Log in, please.