Локальное хранилище или куки? Безопасное хранение JWT на клиенте / Хабр
JWT (JSON Web Token) — это замечательный стандарт, основанный на формате JSON, позволяющий создавать токены доступа, обычно используемые для аутентификации в клиент-серверных приложениях. При использовании этих токенов возникает вопрос о том, как безопасно хранить их во фронтенд-части приложения. Этот вопрос нужно решить сразу же после того, как токен сгенерирован на сервере и передан клиентской части приложения.
Материал, перевод которого мы сегодня публикуем, посвящён разбору плюсов и минусов использования локального хранилища браузера (localStorage
) и куки-файлов для хранения JWT.
Виды токенов
- Токены доступа (access tokens) обычно представляют собой короткоживущие JWT, подписанные сервером. Они включаются в каждый HTTP-запрос, выполняемый клиентом к серверу. Токены используются для авторизации запросов.
- Токены обновления (refresh tokens) обычно представлены долгоживущими токенами, хранящимися в базе данных и используемыми для получения нового токена доступа при истечении срока действия предыдущего токена.
Где именно следует хранить токены на клиенте?
Существует 2 распространённых способа хранения токенов на клиенте: локальное хранилище браузера и куки-файлы. О том, какой способ лучше, много спорят. Большинство людей склоняется в сторону куки-файлов из-за их лучшей защищённости.
Давайте сравним локальное хранилище и куки-файлы. Наше сравнение основано, преимущественно, на этом материале и на комментариях к нему.
Локальное хранилище
▍Преимущества
Основное преимущество локального хранилища заключается в том, что им удобно пользоваться.
- Работа с локальным хранилищем организована очень удобно, тут используется чистый JavaScript. Если у вашего приложения нет бэкенда, и вы полагаетесь на чужие API, не всегда можно запросить у этих API установку особых куки-файлов для вашего сайта.
- Используя локальное хранилище, удобно работать с API, которые требуют размещать токен доступа в заголовок запроса. Например — так:
Authorization Bearer ${access_token}
.
▍Недостатки
Главный недостаток локального хранилища — это его уязвимость к XSS-атакам.
- При выполнении XSS-атаки злоумышленник может запустить свой JavaScript-код на вашем сайте. Это означает, что атакующий может получить доступ к токену доступа, сохранённому в
localStorage
. - Источником XSS-атаки может быть сторонний JavaScript-код, включённый в состав вашего сайта. Это может быть что-то вроде React, Vue, jQuery, скрипта Google Analytics и так далее. В современных условиях почти невозможно разработать сайт, в состав которого не входят библиотеки сторонних разработчиков.
Куки-файлы
▍Преимущества
Главное преимущество куки-файлов заключается в том, что они недоступны из JavaScript. В результате они не так уязвимы к XSS-атакам, как локальное хранилище.
- Если вы используете флаг
HttpOnly
и защищённые куки-файлы, это означает, что из JavaScript нельзя получить доступ к этим файлам. То есть, если даже атакующий сможет запустить свой код на вашей странице, ему не удастся прочитать токен доступа из куки-файла. - Куки автоматически отправляются в каждом HTTP-запросе к серверу.
▍Недостатки
В зависимости от конкретных обстоятельств может случиться так, что токены в куки-файлах сохранить не удастся.
- Размер куки-файлов ограничен 4 Кб. Поэтому, если вы используете большие JWT, хранение их в куки-файлах вам не подойдёт.
- Существуют сценарии, при реализации которых вы не можете передавать куки своему API-серверу. Возможно и то, что какой-то API требует размещения токена в заголовке
Authorization
. В таком случае вы не сможете хранить токены в куки-файлах.
XSS-атаки
Локальное хранилище уязвимо к XSS-атакам из-за того, что с ним очень легко работать, используя JavaScript. Поэтому злоумышленник может получить доступ к токену и воспользоваться им в своих интересах. Однако, хотя HttpOnly-куки и недостижимы из JavaScript, это не означает, что вы, используя куки, защищены от XSS-атак, направленных на кражу токена доступа.
Если атакующий может запускать свой JS-код в вашем приложении, это значит, что он может просто отправить вашему серверу запрос, а токен будет включён в этот запрос автоматически. Такая схема работы просто не так удобна для атакующего, так как он не может прочитать содержимое токена. Но подобное нужно атакующим нечасто. Кроме того, при такой схеме работы злоумышленнику может быть выгоднее атаковать сервер, пользуясь компьютером жертвы, а не собственным.
Куки-файлы и CSRF-атаки
CSRF-атаки — это атаки, в ходе которых пользователя каким-то образом принуждают к выполнению особого запроса. Например, сайт принимает запросы на изменение адреса электронной почты:
POST /email/change HTTP/1.1
Host: site.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 50
Cookie: session=abcdefghijklmnopqrstu
email=myemail.example.com
В такой ситуации атакующий может создать форму со скрытым полем для ввода адреса электронной почты, которая отправляет POST-запрос на
https://site. com/email/change
. При этом сессионные куки автоматически будут включены в такой запрос.
Правда, от этой угрозы можно легко защититься, использовав атрибут
в заголовке ответа и анти-CSRF токены.
Промежуточные итоги
Хотя и куки-файлы не отличаются полной неуязвимостью к атакам, для хранения токенов лучше всего, всегда, когда это возможно, выбирать именно их, а не
localStorage
. Почему?
- И локальное хранилище, и куки уязвимы к XSS-атакам, но злоумышленнику будет сложнее совершить атаку в том случае, если используются HttpOnly-куки.
- Куки уязвимы к CSRF-атакам, но риск таких атак можно смягчить, используя атрибут
SameSite
и анти-CSRF токены.
Куки-файлами можно пользоваться даже в тех случаях, когда надо применять заголовок
Authorization: Bearer
, или когда JWT больше 4 Кб. Это, кроме того, согласуется с
рекомендациямиOWASP: «Не храните идентификаторы сессий в локальном хранилище, так как соответствующие данные всегда доступны из JavaScript. Куки-файлы могут помочь снизить риск благодаря
HttpOnly
».
Использование куки-файлов для хранения токенов OAuth 2.0
Давайте кратко перечислим способы хранения токенов:
- Способ 1: хранение токенов в локальном хранилище. Этот способ подвержен XSS-атакам.
- Способ 2: хранение токенов в HttpOnly-куки. Этот способ подвержен CSRF-атакам, но риск подобных атак может быть смягчён. От XSS-атак этот вариант хранения токенов защищён немного лучше первого.
- Способ 3: хранение токенов обновления в HttpOnly-куки, а токенов доступа — в памяти. Этот способ хранения токенов безопаснее в плане CSRF-атак и немного лучше защищён от XSS-атак.
Ниже мы подробнее рассмотрим третий способ хранения токенов, так как он, из трёх перечисленных, выглядит самым интересным.
Почему хранение токена обновления в HttpOnly-куки безопаснее с точки зрения CSRF-атак?
Злоумышленник может создать форму, которая обращается к
/refresh_token
. В ответ на этот запрос возвращается новый токен доступа. Но атакующий не может прочитать ответ в том случае, если он использует HTML-форму. Для того чтобы не дать атакующему успешно выполнять fetch- или AJAX-запросы и читать ответы, нужно, чтобы CORS-политика сервера авторизации была бы настроена правильно, а именно — так, чтобы сервер не реагировал бы на запросы от неавторизованных веб-сайтов.
Как всё это настроить?
Шаг 1: возврат токена доступа и токена обновления при аутентификации пользователя
После того, как пользователь аутентифицируется, сервер аутентификации возвращает
access_token
(токен доступа) и
refresh_token
(токен обновления). Токен доступа будет включён в тело ответа, а токен обновления — в куки.
Вот что нужно использовать для настройки куки-файлов, предназначенных для хранения токенов обновления:
- Флаг
— чтобы не дать прочесть токен из JavaScript. - Флаг
secure=true
, что приведёт к тому, что данные будут передаваться только по HTTPS. - Флаг
SameSite=strict
нужно использовать всегда, когда это возможно, что позволит защититься от CSRF-атак. Этот подход может использоваться только в том случае, если сервер авторизации относится к тому же сайту, что и фронтенд системы. Если это не так, тогда сервер авторизации должен устанавливать CORS-заголовки на бэкенде, или использовать другие методы для того чтобы убедиться в том, что запрос с токеном обновления может быть выполнен только авторизованным веб-сайтом.
Шаг 2: сохранение токена доступа в памяти
Хранение токена доступа в памяти означает, что токен, в коде фронтенда, записывают в переменную. Это, конечно, означает, что токен будет утерян в том случае, если пользователь закроет вкладку, на которой открыт сайт, или обновит страницу. Именно поэтому у нас имеется токен обновления.
Шаг 3: получение нового токена доступа с использованием токена обновления
Если токен доступа оказывается утраченным или недействительным, нужно обратиться к конечной точке
/refresh_token
. При этом токен обновления, который, на шаге 1, был сохранён в куки-файле, будет включён в запрос. После этого вы получите новый токен доступа, который сможете использовать для выполнения запросов к API.
Всё это значит, что JWT могут быть больше 4 Кб, и то, что их можно помещать в заголовок Authorization
.
Итоги
То, о чём мы тут рассказали, должно дать вам базовую информацию о хранении JWT на клиенте, и о том, как сделать ваш проект безопаснее.
Как вы храните JWT на клиенте?
О хранении JWT токенов в браузерах / Хабр
Открытый стандарт JWT официально появился в 2015 (
rfc7519) обещая интересные особенности и широкие перспективы. Правильное хранение Access токена является жизненно важным вопросов при построении системы авторизации и аутентификации в современном Web, где становятся все популярнее сайты, построенные по технологии SPA.
Неправильное хранение токенов ведет к их краже и переиспользованию злоумышленниками.
Так и где хранить?
Рассмотрим основные варианты хранения JWT Access токена в браузере:
- Local Storage/Session Storage – метод небезопасный и подвержен атакам типа XSS, особенно если Вы подключаете скрипты из сторонних CDN (добавление integrity атрибута не может гарантировать 100% безопасность), либо не уверены что подключаемые Вами скрипты не имеют возможности «слить» данные из хранилищ на сторону. Более того если Local Storage доступен между табами то Session Storage доступен только в одной вкладке и открытие сайта в новой вкладке лишь вызовет новый раунд авторизации/рефреша Access токена.
- Хранение токена в локальной переменной внутри замыкания тоже не обеспечивает должной безопасности потому что атакующий может, например, проксировать функцию fetch и отправить токен на левый сайт. Также это не решает проблему двух вкладок – нет безопасного способа передать токен из одной вкладки в другую.
- Cookies. Вот мы вернулись к старым «печенькам» которые использовались для хранения cookie sessions. Простое хранения Access токена в cookie чревато атакой CSRF. Более того оно не защищает от XSS атак. Для защиты от CSRF нужно ставить параметр Cookie SameSite в режим Strict– этим можно добиться того что все запросы, которые идут с других сайтов, не будут содержать Ваши credentials, что автоматически лишит атакующего возможности произвести CSRF атаку.
В отличии от первых двух вариантов здесь есть и плюс – Access токен невозможно получить через JS если использовать флаг httpOnly, добавление Secure также усилит защиту от сниффинга.Важным моментом является установка Cookie только для api домена/пути, чтобы запросы к публичной статике не содержали оверхед в header.
Что в итоге?
Cookies при правильном использовании являются адекватным и наиболее безопасным на данный момент решением для хранения JWT Access токена и должны следовать следующим правилам:
- Быть установленными для API домена/пути чтобы избежать оверхеда при запросах к статичным файлам (публичным картинкам/стилям/js файлам).
- Иметь флаг Secure (для передачи только по https).
- Иметь флаг httpOnly (для невозможности получения доступа из JavaScript).
- Атрибут SameSite должен быть Strict для защиты от CSRF аттак, запретит передачу Cookie файлов если переход к вашему API был не с установленого в Cookie домена.
На стороне сервера также должно быть настроено:
- Content-Security-Policy – ограничение доверенных доменов для предотвращения возможных XSS атак
- Заголовок X-Frame-Options для защиты от атак типа clickjacking.
- X-XSS-Protection – принудительно включить встроенный механизм защиты браузера от XSS атак.
- X-Content-Type-Options – для защиты от подмены MIME типов.
Соблюдение этих мер вкупе с частой ротацией Access/Refresh токенов должно помочь обеспечить высокий уровень безопасности на сайте.
Ограничения
Не смотря на то что атрибут
SameSiteподдерживается во многих популярных
браузерах, существуют также браузеры которые не поддерживают его или поддерживают частично (привет IE и Safari для мака). Для этих случаев нужен fallback к CSRF токенам. В этом случае вместе с запросами к API надо передавать и CSRF токен. Правильный CSRF токен должен генерироваться сервером с учетом
Fingerprint’aпользователя дабы минимизировать вероятность его подмены.
Безопасность JSON Web Tokens (JWT)
Безопасность JSON Web Tokens (JWT)
Введение
В последнее время все чаще можно встретить приложения, использующие для аутентификации пользователей механизмы JSON Web Tokens. Особую популярность JWT завоевал с ростом популярности микросервисной архитектуры: он возлагает задачу по обработке аутентификационных данных на сами микросервисы, а следовательно позволяет избежать различных ошибок авторизации, увеличить производительность и улучшить масштабируемость приложения.
Вместе с тем неправильное использование JWT может негативно сказаться на безопасности приложения. Мы приведем примеры использования JWT, разберем распространенные ошибки в реализации схем аутентификации с применением JWT, рассмотрим основные виды атак на эти схемы и дадим рекомендации по их предотвращению.
Формат JWT: описание
В этом разделе статьи мы расскажем, что такое JSON Web Tokens, из каких частей он состоит, как используется для аутентификации пользователей и в чем заключается преимущество JWT в сравнении с классической схемой аутентификации с использованием сессий.
Структура JWT
Согласно RFC-7519, JSON Web Tokens — один из способов представления данных для передачи между двумя или более сторонами в виде JSON-объекта.
Как правило, структурно JWT состоит из трех частей:
- header — заголовок,
- payload — полезная нагрузка,
- signature — подпись.
Бывают и исключения, когда в JWT отсутствует подпись. Подобный случай будет рассмотрен далее.
Заголовок и полезная нагрузка — обычные JSON-объекты, которые необходимо дополнительно закодировать при помощи алгоритма base64url. Закодированные части соединяются друг с другом, и на их основе вычисляется подпись, которая также становится частью токена.
В общем случае токен выглядит следующим образом:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjEzMzciLCJ1c2VybmFtZSI6ImJpem9uZSIsImlhdCI6MTU5NDIwOTYwMCwicm9sZSI6InVzZXIifQ.ZvkYYnyM929FM4NW9_hSis7_x3_9rymsDAx9yuOcc1I
На рис. 1 можно увидеть, что токен состоит из трех частей, разделенных точками.
Рис. 1. JSON Web Token (пример с сайта jwt.io)Красная часть — заголовок:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
В исходном виде:
{ "typ": "JWT", "alg": "HS256" }
Фиолетовая часть — полезная нагрузка:
eyJpZCI6IjEzMzciLCJ1c2VybmFtZSI6ImJpem9uZSIsImlhdCI6MTU5NDIwOTYwMCwicm9sZSI6InVzZXIifQ
В исходном виде:
{ "id": "1337", "username": "bizone", "iat": 1594209600, "role": "user" }
Голубая часть — подпись:
ZvkYYnyM929FM4NW9_hSis7_x3_9rymsDAx9yuOcc1I
Рассмотрим структуру полей более подробно.
Заголовок
Заголовок — служебная часть токена. Он помогает приложению определить, каким образом следует обрабатывать полученный токен.
Эта часть, как было ранее упомянуто, является JSON-объектом и имеет следующий формат:
{ "typ": "JWT", "alg": "HS256" }
Здесь присутствуют следующие поля:
- typ — тип токена, например JWT;
- alg — алгоритм, использованный для генерации подписи.
Значение поля typ зачастую игнорируется приложениями, однако стандарт не рекомендует отказываться от него для обеспечения обратной совместимости.
Поле alg обязательно для заполнения. В приведенном случае был применен алгоритм HS256 (HMAC-SHA256), в котором для генерации и проверки подписи используется единый секретный ключ.
Для подписи JWT могут применяться и алгоритмы асимметричного шифрования, например RS256 (RSA-SHA256). Стандарт допускает использование и других алгоритмов, включая HS512, RS512, ES256, ES512, none и др.
Использование алгоритма none указывает на то, что токен не был подписан. В подобном токене отсутствует часть с подписью, и установить его подлинность невозможно.
Полезная нагрузка
В полезной нагрузке передается любая информация, которая помогает приложению тем или иным образом идентифицировать пользователя. Дополнительно могут передаваться определенные служебные поля, однако они не обязательны для заполнения, поэтому на них останавливаться мы не будем.
В нашем случае полезная нагрузка содержит следующий JSON-объект:
{ "id": "1337", "username": "bizone", "iat": 1594209600, "role": "user" }
Здесь присутствуют следующие поля:
- id — уникальный идентификатор пользователя;
- username — имя пользователя;
- iat — служебное поле, время генерации токена в формате Unix time;
- role — роль пользователя, например admin, user, guest.
Поскольку набор полей в части полезной нагрузки произвольный, приложение может хранить в этой части практически любые данные. Например, для ускорения работы приложения в полезной нагрузке могут храниться Ф. И. О. пользователя, чтобы не запрашивать эти сведения каждый раз из базы данных.
Подпись
Подпись генерируется следующим образом.
Заголовок и полезная нагрузка кодируются при помощи алгоритма base64url, после чего объединяются в единую строку с использованием точки ("."
) в качестве разделителя.
Генерируется подпись (в нашем примере — с применением алгоритма HMAC-SHA256), которая добавляется к исходной строке так же через точку.
На псевдокоде алгоритм выглядит примерно так:
signature = HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), SECRET_KEY ) JWT = base64UrlEncode(header) + ". " + base64UrlEncode(payload) + "." + base64UrlEncode(signature)
Получив JWT от пользователя, приложение самостоятельно вычислит значение подписи и сравнит его с тем значением, которое было передано в токене. Если эти значения не совпадут, значит, токен был модифицирован или сгенерирован недоверенной стороной, и принимать такой токен и доверять ему приложение не будет.
Подпись приведенного в пример токена можно проверить с использованием секретного ключа test (например, на сайте jwt.io).
Аутентификация с использованием JWT
Схема аутентификации с использованием JWT предельно проста.
Пользователь вводит свои учетные данные в приложении или доверенном сервисе аутентификации. При успешной аутентификации сервис предоставляет пользователю токен, содержащий сведения об этом пользователе (уникальный идентификатор, Ф. И. О., роль и т. д.).
При последующих обращениях токен передается приложению в запросах от пользователя (в cookie, заголовках запроса, POST- или GET-параметрах и т. д.).
Получив токен, приложение сперва проверяет его подпись. Убедившись, что подпись действительна, приложение извлекает из части полезной нагрузки сведения о пользователе и на их основе авторизует его.
Преимущества JWT
Перечислим преимущества использования JWT в сравнении с классической схемой аутентификации, использующей сессии.
Во-первых, подход с использованием токенов позволяет не хранить информацию обо всех выданных токенах, как при классической схеме. Когда пользователь обращается к приложению, он передает ему свой токен. Приложению остается только проверить подпись и извлечь необходимые поля из полезной нагрузки.
Во-вторых, приложению вообще не обязательно заниматься выдачей и валидацией токенов самостоятельно, зачастую для этих целей используется отдельный сервис аутентификации.
В-третьих, при использовании отдельного сервиса аутентификации становится возможным организовать единую точку входа в различные сервисы с одними и теми же учетными данными. Единожды пройдя процедуру аутентификации, пользователь сможет получить доступ со своим токеном к тем ресурсам, которые доверяют этому сервису аутентификации.
В-четвертых, как было указано ранее, приложение может хранить в части полезной нагрузки практически любые данные, что при грамотной архитектуре приложения может существенно увеличить производительность.
Благодаря перечисленным факторам схема аутентификации с использованием JWT широко используется в различных корпоративных приложениях. Особенно популярна эта схема в тех приложениях, которые реализуют парадигмы микросервисной архитектуры: при таком подходе каждый сервис получает необходимые ему сведения о пользователе непосредственно из токена, а не тратит время на получение этой информации из базы данных.
Формат JWT: атаки
В этом разделе будут рассмотрены основные атаки на JWT и даны рекомендации по их предотвращению.
Перехват токена
Перехват пользовательского токена может привести к ряду неприятных последствий.
Во-первых, так как JWT передается в открытом виде, для получения хранящихся в части полезной нагрузки исходных данных достаточно применить к этой части функцию base64UrlDecode. То есть злоумышленник, перехвативший токен, сможет извлечь хранящиеся в токене данные о пользователе.
В соответствии с лучшими практиками для предотвращения подобной угрозы рекомендуется:
- использовать при передаче токенов защищенное соединение;
- не передавать в токенах чувствительные пользовательские данные, ограничившись обезличенными идентификаторами.
Во-вторых, злоумышленник, перехвативший токен, сможет его переиспользовать и получить доступ к приложению от лица пользователя, чей JWT был перехвачен.
Здесь рекомендации будут следующие:
- как и в первом случае, использовать защищенное соединение при передаче токенов;
- ограничить время жизни JWT и использовать механизм refresh tokens.
Refresh tokens
В современных схемах аутентификации, основанных на JWT, после прохождения аутентификации пользователь получает два токена:
- access token — JWT, на основе которого приложение идентифицирует и авторизует пользователя;
- refresh token — токен произвольного формата, служащий для обновления access token.
Access token при таком подходе имеет сильно ограниченное время жизни (например, одну минуту). Refresh token же имеет длительное время жизни (день, неделя, месяц), но он одноразовый и служит исключительно для обновления access token пользователя.
Схема аутентификации в таком случае выглядит следующим образом:
- пользователь проходит процедуру аутентификации и получает от сервера access token и refresh token;
- при обращении к ресурсу пользователь передает в запросе свой access token, на основе которого сервер идентифицирует и авторизует клиента;
- при истечении access token клиент передает в запросе свой refresh token и получает от сервера новые access token и refresh token;
- при истечении refresh token пользователь заново проходит процедуру аутентификации.
Подбор ключа симметричного алгоритма подписи
При использовании симметричных алгоритмов для подписи JWT (HS256, HS512 и др.) злоумышленник может попытаться подобрать ключевую фразу.
Подобрав ее, злоумышленник получит возможность манипулировать JWT-токенами так, как это делает само приложение, а следовательно сможет получить доступ к системе от лица любого зарегистрированного в ней пользователя.
В нашем примере из первой части статьи для подписи JWT в качестве ключевой фразы была использована строка test. Она простая, короткая и содержится во всех основных словарях для перебора паролей. Злоумышленнику не составит труда подобрать эту ключевую фразу с использованием программ John the Ripper
или hashcat
.
Рекомендации для защиты от атаки в этом случае такие:
- использовать ключевые фразы большой длины, состоящие из больших и малых букв латинского алфавита, цифр и спецсимволов, и хранить их в строгой конфиденциальности;
- обеспечить периодическую смену ключевой фразы. Это снизит удобство использования для пользователей (поскольку время от времени им придется проходить процедуру аутентификации заново), но поможет избежать компрометации ключевой информации.
Использование алгоритма none
Как было упомянуто в первой части статьи, использование в заголовке JWT алгоритма none указывает на то, что токен не был подписан. В подобном токене отсутствует часть с подписью, и установить его подлинность становится невозможно.
Рассмотрим подобную атаку на нашем примере. Наш токен в незакодированном виде выглядит следующим образом:
header: { "typ": "JWT", "alg": "HS256" } payload: { "id": "1337", "username": "bizone", "iat": 1594209600, "role": "user" } signature: ZvkYYnyM929FM4NW9_hSis7_x3_9rymsDAx9yuOcc1I
Предположим, мы хотим, чтобы приложение считало нас администратором. Для этого необходимо установить значение admin в поле role полезной нагрузки. Но при внесении в токен этого изменения подпись токена станет невалидной, и приложение не примет такой JWT.
Для обхода защитного механизма мы можем попытаться изменить значение поля alg в заголовке токена на none. Наш токен примет следующий вид:
header: { "typ": "JWT", "alg": "none" } payload: { "id": "1337", "username": "bizone", "iat": 1594209600, "role": "admin" }
Поскольку мы используем алгоритм none, подпись отсутствует. В закодированном виде наш JWT будет выглядеть так:
eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJpZCI6IjEzMzciLCJ1c2VybmFtZSI6ImJpem9uZSIsImlhdCI6MTU5NDIwOTYwMCwicm9sZSI6ImFkbWluIn0
Этот токен мы и передадим на сервер. Уязвимое приложение, проверив заголовок JWT и обнаружив в нем alg: none, примет этот токен без всяких проверок, как если бы он был легитимным, в результате чего мы получим привилегии администратора.
Чтобы защититься от такой атаки:
- необходимо вести на стороне приложения белый список разрешенных алгоритмов подписи и отбрасывать все токены с алгоритмом подписи, отличным от разрешенного на сервере;
- желательно работать строго с одним алгоритмом, например HS256 или RS256.
Изменение алгоритма подписи
При использовании асимметричных алгоритмов подпись токена осуществляется с использованием приватного ключа сервиса, а проверка подписи — с использованием публичного ключа сервиса.
Некоторые реализации библиотек для работы с JWT содержат логические ошибки, заключающиеся в том, что при получении токена, подписанного с использованием симметричного алгоритма (например, HS256), для проверки подписи в качестве ключевой фразы будет использован публичный ключ сервиса. Поскольку публичный ключ сервиса не засекречен, злоумышленник может легко получить его и использовать для подписи собственных токенов.
Для рассмотрения примера этого варианта атаки нам понадобится новый JWT:
header: { "alg": "RS256", "typ": "JWT" } payload: { "id": "1337", "username": "bizone", "iat": 1594209600, "role": "user" } signature: YLOVSKef-paSnnM8P2JLaU2FiS8TbhYqjewLmgRJfCj1Q6rVehAHQ-lABnKoRjlEmHZX-rufHEocDxGUYiGMjMexUQ3zt-WqZITvozJ4pkvbV-mJ1nKj64NmqaR9ZkBWtmF-PHJX50eYjgo9rzLKbVOKYOUa5rDkJPHP3U0aaBXFP39zsGdOTuELv436WXypIZBeRq2yA_mDh23TvzegWCK5sjD4Gh277bCq57tBYjhGIQrDypVe4cWBPlvwFlmG8tdpWGu0uFp0GcbTAfLUlbTSuGROj88BY0XeUs0iqmGlEICES3uqNx7vEmdT5k_AmL436SLedE0VHcyxve5ypQ
В кодированном виде он будет выглядеть следующим образом:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjEzMzciLCJ1c2VybmFtZSI6ImJpem9uZSIsImlhdCI6MTU5NDIwOTYwMCwicm9sZSI6InVzZXIifQ.YLOVSKef-paSnnM8P2JLaU2FiS8TbhYqjewLmgRJfCj1Q6rVehAHQ-lABnKoRjlEmHZX-rufHEocDxGUYiGMjMexUQ3zt-WqZITvozJ4pkvbV-mJ1nKj64NmqaR9ZkBWtmF-PHJX50eYjgo9rzLKbVOKYOUa5rDkJPHP3U0aaBXFP39zsGdOTuELv436WXypIZBeRq2yA_mDh23TvzegWCK5sjD4Gh277bCq57tBYjhGIQrDypVe4cWBPlvwFlmG8tdpWGu0uFp0GcbTAfLUlbTSuGROj88BY0XeUs0iqmGlEICES3uqNx7vEmdT5k_AmL436SLedE0VHcyxve5ypQ
Поскольку в этом случае мы используем для подписи алгоритм RS256, нам понадобятся публичный и приватный ключи.
Публичный ключ:
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc aT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIy tvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0 e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWb V6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9 MwIDAQAB -----END PUBLIC KEY-----
Приватный ключ:
-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEAnzyis1ZjfNB0bBgKFMSvvkTtwlvBsaJq7S5wA+kzeVOVpVWw kWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHcaT92whREFpLv9cj5lTeJSibyr/Mr m/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIytvHWTxZYEcXLgAXFuUuaS3uF9gEi NQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0e+lf4s4OxQawWD79J9/5d3Ry0vbV 3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWbV6L11BWkpzGXSW4Hv43qa+GSYOD2 QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9MwIDAQABAoIBACiARq2wkltjtcjs kFvZ7w1JAORHbEufEO1Eu27zOIlqbgyAcAl7q+/1bip4Z/x1IVES84/yTaM8p0go amMhvgry/mS8vNi1BN2SAZEnb/7xSxbflb70bX9RHLJqKnp5GZe2jexw+wyXlwaM +bclUCrh9e1ltH7IvUrRrQnFJfh+is1fRon9Co9Li0GwoN0x0byrrngU8Ak3Y6D9 D8GjQA4Elm94ST3izJv8iCOLSDBmzsPsXfcCUZfmTfZ5DbUDMbMxRnSo3nQeoKGC 0Lj9FkWcfmLcpGlSXTO+Ww1L7EGq+PT3NtRae1FZPwjddQ1/4V905kyQFLamAA5Y lSpE2wkCgYEAy1OPLQcZt4NQnQzPz2SBJqQN2P5u3vXl+zNVKP8w4eBv0vWuJJF+ hkGNnSxXQrTkvDOIUddSKOzHHgSg4nY6K02ecyT0PPm/UZvtRpWrnBjcEVtHEJNp bU9pLD5iZ0J9sbzPU/LxPmuAP2Bs8JmTn6aFRspFrP7W0s1Nmk2jsm0CgYEAyH0X +jpoqxj4efZfkUrg5GbSEhf+dZglf0tTOA5bVg8IYwtmNk/pniLG/zI7c+GlTc9B BwfMr59EzBq/eFMI7+LgXaVUsM/sS4Ry+yeK6SJx/otIMWtDfqxsLD8CPMCRvecC 2Pip4uSgrl0MOebl9XKp57GoaUWRWRHqwV4Y6h8CgYAZhI4mh5qZtnhKjY4TKDjx QYufXSdLAi9v3FxmvchDwOgn4L+PRVdMwDNms2bsL0m5uPn104EzM6w1vzz1zwKz 5pTpPI0OjgWN13Tq8+PKvm/4Ga2MjgOgPWQkslulO/oMcXbPwWC3hcRdr9tcQtn9 Imf9n2spL/6EDFId+Hp/7QKBgAqlWdiXsWckdE1Fn91/NGHsc8syKvjjk1onDcw0 NvVi5vcba9oGdElJX3e9mxqUKMrw7msJJv1MX8LWyMQC5L6YNYHDfbPF1q5L4i8j 8mRex97UVokJQRRA452V2vCO6S5ETgpnad36de3MUxHgCOX3qL382Qx9/THVmbma 3YfRAoGAUxL/Eu5yvMK8SAt/dJK6FedngcM3JEFNplmtLYVLWhkIlNRGDwkg3I5K y18Ae9n7dHVueyslrb6weq7dTkYDi3iOYRW8HRkIQh06wEdbxt0shTzAJvvCQfrB jg/3747WSsf/zBTcHihTRBdAv6OmdhV4/dD5YBfLAkLrd+mX7iE= -----END RSA PRIVATE KEY-----
Для тестов мы будем использовать сайт jwt. io (рис. 2).
Рис. 2. Исходный JWTКак и в предыдущем примере, модифицируем токен:
header: { "typ": "JWT", "alg": "HS256" } payload: { "id": "1337", "username": "bizone", "iat": 1594209600, "role": "admin" }
В кодированном виде заголовок и полезная нагрузка будут выглядеть следующим образом:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjEzMzciLCJ1c2VybmFtZSI6ImJpem9uZSIsImlhdCI6MTU5NDIwOTYwMCwicm9sZSI6ImFkbWluIn0
Остается только подсчитать подпись с использованием публичного ключа сервиса.
Для начала переводим ключ в hex-представление (рис. 3).
Рис. 3. Hex-представление ключаЗатем генерируем подпись с использованием openSSL (рис. 4).
Рис. 4. Генерация подписи для JWT
Полученное значение E1R1nWNsO-H7h5WoYCBnm6c1zZy-0hu2VwpWGMVPK2g
добавляем к уже имеющейся строке, и наш токен принимает следующий вид:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9. eyJpZCI6IjEzMzciLCJ1c2VybmFtZSI6ImJpem9uZSIsImlhdCI6MTU5NDIwOTYwMCwicm9sZSI6ImFkbWluIn0.E1R1nWNsO-H7h5WoYCBnm6c1zZy-0hu2VwpWGMVPK2g
Подставляем в поле secret на jwt.io наш публичный ключ, и JWT успешно проходит проверку (не забудьте поставить галочку secret base64 encoded!) (рис. 5).
Рис. 5. Успешная проверка подписи JWTДля предотвращения такой атаки рекомендуется:
- работать только с одним алгоритмом, например HS256 или RS256;
- выбирать хорошо известные и проверенные библиотеки для работы с JWT, которые с меньшей вероятностью содержат логические ошибки в процедурах проверки токенов.
Манипуляция ключевыми идентификаторами
Стандарт RFC-7515 описывает параметр заголовка kid (Key ID, идентификатор ключа). Вместе с тем стандарт говорит о том, что формат этого поля строго не определен. Поэтому разработчики вольны интерпретировать его так, как удобно им, что зачастую приводит к различным ошибкам.
Для примера возьмем следующий заголовок JWT:
{ "alg" : "HS256", "typ" : "JWT", "kid" : "1337" }
Предполагается, что для проверки токена будет использован хранящийся в БД ключ с идентификатором 1337. В случае ошибок кодирования это поле может быть уязвимо к SQL-инъекции:
{ "alg" : "HS256", "typ" : "JWT", "kid" : "1337' union select 'SECRET_KEY' -- 1" }
В таком случае для проверки подписи ключа в качестве ключевой фразы вместо предполагаемого ключа из базы данных будет использована строка SECRET_KEY.
В следующем примере предположим, что для проверки токена будет использован ключ из файла keys/service3.key.
{ "alg" : "HS256", "typ" : "JWT", "kid" : "keys/service3.key" }
Если параметр не валидируется, злоумышленник сможет провести атаку Path Traversal (Directory Traversal) и вместо предполагаемого пути до файла с ключом передаст в поле kid путь до какого-либо публичного файла:
{ "alg" : "HS256", "typ" : "JWT", "kid" : ". ./../../images/public/cat.png" }
Злоумышленник может получить доступ к файлу cat.png и подписать JWT с использованием содержимого этого файла, поскольку этот файл общедоступный (например, он опубликован на одной из страниц сервиса). Сервис же, получив в поле kid путь до файла cat.png, использует его содержимое в качестве ключевого файла для проверки подписи токена (которая окажется успешной, ведь злоумышленник заранее об этом позаботился).
Рекомендация по предотвращению подобных атак простая: необходимо всегда валидировать и санитизировать полученные от пользователя данные, даже если они были получены в виде JWT.
Заключение
JSON Web Tokens — популярная и удобная технология. При правильном использовании JWT избавляет от распространенных ошибок недостаточной авторизации, позволяет просто и удобно распределить информационные потоки между сервисами, организовать единую точку входа в различные сервисы с одними и теми же учетными данными и даже повысить производительность сервиса.
Вместе с тем при неправильном использовании JWT можно подвергнуть свою систему существенным рискам, вплоть до компрометации учетных записей абсолютно всех пользователей системы.
Итак, для безопасного использования JWT следует:
- использовать защищенное соединение при передаче токенов;
- не передавать в токенах чувствительные пользовательские данные;
- ограничить время жизни JWT и использовать механизм refresh tokens;
- использовать ключевые фразы большой длины;
- обеспечить периодическую смену ключевой фразы;
- вести на стороне приложения белый список разрешенных алгоритмов подписи;
- в идеальном случае работать строго с одним алгоритмом подписи;
- выбирать хорошо известные и проверенные библиотеки для работы с JWT;
- всегда валидировать и санитизировать полученные от пользователя данные.
Где Хранить Токены ERC20? Лучшие Кошельки [2020]
Как выбрать кошелек для токенов ERC20?
Почти все владельцы токенов ERC20 (Basic Attention Token, OmiseGO и другие) интересуются самыми безопасными и самыми надежными кошельками под монеты ERC20.
Благодаря процветанию проектов на основе Эфира и появлению на рынке новых монет на основе Эфира, которые появляются почти каждый день, интерес к кошелькам ERC20 становится все больше и больше.
Сегодня Ethereum – одна из самых популярных блокчейн-платформ для смарт контрактов и DApp, на которой размещено более 550 токенов. Это, естественно, требует наличия надежного кошелька для этих токенов ERC20.
Эти токены называются токенами ERC20 или токенами на основе Ethereum, поскольку все они следуют аналогичному набору правил на ранних этапах реализации.
Со временем эти токены вырастут в цене и потенциально могут сделать Вас богатыми, если Вы будете хранить их в безопасности в течение длительного времени. Следовательно, уместно хранить Ваши монеты ERC20 в кошельке со следующими функциями:
- Приватные ключи — кошельки, где вы контролируете свои личные ключи.
- Простота использования — удобный интерфейс.
- Сообщество разработчиков — сообщество активных разработчиков.
- Резервное копирование и безопасность — резервное копирование и восстановление функций.
- Совместимость — совместимость с различными операционными системами.
Лучшие доступные кошельки ERC20
Ниже представлен список удобный кошельков, которые без проблем позволяют Вам хранить монеты ERC20.
Это как аппаратные кошельки, так и мобильные, веб кошельки и другие.
Atomic Wallet
Если на первом месте для Вас стоят простота и надежность – то мультивалютный кошелек Atomic Wallet будет идеальным инструментом для хранения монет ERC-20.
Во-первых, кошелек дает возможность создания сложного пароля, а во-вторых (что самое главное), генерируемая SEED фраза хранится только на Вашем компьютере, что означает, что только Вы управляете своими деньгами!
Atomic Wallet предназначен для того, чтобы быть достаточно простым для использования любым пользователем, даже без какого-либо технического опыта.
Atomic Wallet позволяет надежно хранить десятки монет ERC-20, к примеру, такие как:
- Ethereum
- Tether (USDT)
- Ethereum Classic
- Ontology
- Tezos
- Lisk
- Maker
И многие другие монеты, с которыми Вы можете ознакомиться на официальном сайте кошелька.
Хранение токенов ERC-20 на Atomic Wallet
Для того, чтобы хранить нужную Вам монету (монеты) ERC-20, скачайте кошелек Atomic Wallet с официального сайта под нужную Вам операционную систему:
Запустите установку кошелька. После того, как кошелек запустится нажмите на кнопку «New Wallet».
Далее, на следующей странице придумайте и впишите надежный пароль. Желательно использовать несуществующие слова, к примеру:
«TGhdwui12554PPGMqfhz12»
Теперь для доступа и восстановления своего кошелька необходимо сделать следующее:
«Пожалуйста, запишите резервную фразу из 12 слов и храните копию в надежном месте. Это позволит Вам восстановить свой кошелек в любое время»
Обязательно запишите SEED фразу на бумажный носитель!
После того, как Вы переписали seed фразу, нажмите на кнопку «Open Wallet».
На этом все, Ваш кошелек готов к использованию!
Теперь в открывшемся кошельке, в левом верхнем углу, в поле «Search…» начните вводить название нужной Вам криптовалюты. К примеру, впишите ETC, если Вы хотите хранить монеты Ethereum Classic, или в общем списке монет, найдите те, которые Вам нужны.
Обратите внимание, что напротив каждой монеты пишется следующая информация:
- Количество ETC (в случае примера ERC-20 монеты), которое хранится на кошельке
- Значение в Долларах (Всего Вашего ETC, или другой монеты)
- Цена монеты (в нашем случае цена ETC)
- Рост или падение криптовалюты в процентном соотношении
Для того, чтобы создать новый кошелек – нажмите на название монеты. В открывшемся окне нажмите на кнопку «Receive». Откроется новая страница, на которой будет отображен Ваш кошелек!
Скопируйте его, чтобы переместить Ваши ETC (или другие ERC-20 монеты) монеты на кошелек Atomic Wallet.
На этом все, Вы создали кошелек для монеты ERC-20 и теперь можете надежно хранить тут монеты
Обратите внимание, что Atomic Wallet – это не только надежный кошелек, но и то место, где Вы можете заработать. Вы можете положить в стейкинг следующие монеты (чтобы заработать на них):
- COSMOS
- Tezos
- Ontology
- Tron
- Komodo
- Neo
И другие монеты, со всем списком стейкинг монет, Вы можете ознакомиться на официальном сайте кошелька!
Ledger Nano S [Аппаратный кошелек]
Мы много говорили о Ledger Nano S на нашем сайте, говорили о его плюсах и минусах. Повторимся, этот кошелек очень удобен, так как прост в использовании.
Он претендует на то, чтобы быть офлайновым кошельком, поскольку он использует браузер компьютера для генерации необходимых данных, и на серверах Ledger Nano S ничего не сохраняется. Кроме того, Вы получаете контроль приватного ключа, поэтому Вам не нужно доверять третьим сторонам для обеспечения безопасности Ваших средств.
У кошелька есть активная команда разработчиков. Он имеет следующие степени защиты:
Встроенная функция безопасности – PIN код
Seed ключи
Парольные фразы
Кроме того, он поддерживает более 20 криптовалют в одном устройстве и постоянно разрабатывается для обеспечения безопасности еще нескольких валют.
То есть по факту, Вы получаете флешку-сейф, в которой можете без проблем хранить криптовалюты и в любой момент быстро и удобно перекинуть их на биржу или кошелек.
Вы можете использовать любой токен ERC20 на Ledger Nano S. Это также самый дешевый мультивалютный аппаратный кошелек за 65$.
Плюсы: удобный экран, устройство защищено металлической поворотной крышкой, мультивалютный, сторонние приложения могут запускаться с этого устройства, поддержка U2F, при восстановлении кошелька весь процесс можно выполнить с устройства, даже не подключая его к компьютеру, довольно недорогой (~ 65 долларов США)
Минусы: не очень передовое программное обеспечение кошелька (без маркировки транзакций), нет возможности создавать скрытые аккаунты, нет менеджера паролей.
Купить Ledger Nano S Вы можете в официальном магазине.
Trezor [Аппаратный кошелек]
Кошелек Trezor является одним из старейших аппаратных кошельков в криптосфере, и неудивительно, что он поддерживает все токены ERC20.
Как и в Ledger, Trezor также поставляется с экраном OLED, для удобства пользования.
Недавно на нашем YouTube канале мы опубликовали видео: первые впечатления от использования аппаратного кошелька Trezor.
Он имеет следующие функции безопасности:
- Защита с помощью PIN-кода
- Парольная фраза
Кроме того, команда разработчиков Trezor очень активна и уважаема в сообществе.
Trezor, безусловно, еще один аппаратный кошелек, который вы можете использовать для любого типа токена ERC20. Вот официальное руководство по использованию токенов ERC20 на устройстве Trezor.
Trezor доступен в 3 цветах — белом, сером и черном.
Плюсы: надежная безопасность и конфиденциальность, функция холодного хранения, простой в использовании веб-интерфейс, встроенный экран, программное обеспечение с открытым исходным кодом, очень прост и легок для начинающих.
Минусы: стоит 99 Евро (без скидки), должно быть устройство с доступом в Интернет для отправки токенов ERC20.
Вы можете купить Trezor по нашей партнерской программе со скидкой всего за 69 Евро по ссылке: https://shop.trezor.io/product/trezor-one-white
Также мы советуем Вам посмотреть настройку кошелька Trezor с нашего YouTube канала, что бы понять на сколько он прост и удобен в использовании:
MyEtherWallet [Веб-кошелек]
MyEtherWallet – это один из самых распространенных кошельков, когда дело доходит до управления токенами ERC20.
Хранение токенов ERC20 на MyEtherWallet не вызывает у пользователей каких либо проблем и жалоб.
MyEtherWallet — это веб-кошелек с открытым исходным кодом, написанный на Javascript. Это удобное приложение для защиты токенов Ether, ERC20 и взаимодействия с интеллектуальными контрактами.
Но при всем при этом у него все равно есть минусы.
Поскольку это горячий кошелек, лучше не хранить на нем много средств. Но если Вы используете MyEtherWallet с Ledger Nano S, это лучший кошелек для использования, потому что Ваши средства не могут быть украдены.
В интерфейсе веб-браузера вы даже можете использовать ERC20, хранящийся на Вашем аппаратном кошельке Trezor или Ledger Nano S, через MyEtherWallet.
Узнать как перемещать токены ERC20 с Ledger Nano S на MyEtherWallet Вы можете здесь.
MetaMask [веб-кошелек]
MetaMask — еще один простой в использовании кошелек Ethereum, который нравится большому числу пользователей и которым можно пользоваться бесплатно.
Это похоже на браузер для доступа к сети Ethereum. Он не только позволяет хранить и отправлять Ethereum, но и позволяет управлять на нем токенами ERC20.
Кроме того, у него есть активная команда разработчиков, которая разработала MetaMask таким образом, чтобы Вы всегда контролировали свои средства с помощью начального ключа, который вы получаете во время начальной настройки.
Кошелек имеет интуитивно понятный дизайн, в котором вы можете легко переключаться между тестовой сетью и основной сетью Ethereum.
Ниже представлено видео с официального youtube канала MetaMask, демонстрирующее, как работает кошелек:
Читайте: Что такое MetaMask? Как он работает, безопасность? Пошаговая инструкция по установке
Coinomi [Мобильный кошелек]
Coinomi — это популярный мультивалютный мобильный кошелек, получивший известность благодаря поддержке форков монет. Но точно так же, как кошелек с активным сообществом и активной командой разработчиков, Coinomi также поддерживает токены на основе Ethereum и Ethereum (токены ERC20).
Кроме того, этот кошелек всегда контролирует ваши средства, так как это HD-кошелек с PIN-кодом, начальным ключом и парольной фразой, которую вы можете включить в любое время.
Однако функция токенов не включена по умолчанию в Coinomi, поэтому вам нужно сначала настроить ее, а затем включить опцию токенов, добавив выбранные токены.
Вот как вы это можете сделать:
Перейдите в раздел с обзором кошелька и нажмите «+ TOKENS»
Нажмите на «Ethereum», чтобы увидеть список токенов.
Теперь выберите свой токен и нажмите «FINISH»
Кошелек coinomi доступен как для Android, так и для IOS.
Trust [Мобильный кошелек]
Trust wallet — это мобильный кошелек, который в последнее время приобрел довольно большую популярность после приобретения его Binance.
Trust кошелек — это кошелек для токенов ERC20 на основе Ethereum и токенов ERC223 . Здесь, в этом кошельке, Ваш личный ключ хранится только локально и защищен многими уровнями безопасности.
С помощью этого кошелька отправляйте, получайте, храните и отслеживайте Ethereum (ETH), Ethereum Classic (ETC), Callisto (CLO) и более 30000 поддерживаемых токенов ERC20, включая EOS, OmiseGO, Qtum, Kyber Network, EOS, BAT, TenXPay и Augur и многие другие.
Trust кошелек также действует как браузер Web3, который позволяет взаимодействовать с децентрализованными приложениями (DApp) непосредственно из приложения.
Вывод
Если вы внимательно наблюдаете за криптовалютами, то можно сказать, что экосистема Эфира очень быстро развивается. Таким образом, Вы не должны столкнуться с какими-либо трудностями при поиске подходящего токена ERC20 для себя и кошелька под него.
Но мы предупреждаем! Если у монеты есть свой холодный или веб кошелек (официальный кошелек проекта),то храните монеты на нем! Не доверяется свои деньги мультивалютным кошелькам.Это связано с тем, что такие типы кошельков могут в любой момент закрыться и все ваши средства будут потеряны / украдены.
Безусловно существует еще огромное количество такого типа кошельков и в будущем мы обязательно расширем этот списов. Примером могут служить:
Мы надеемся, что этот список кошельков ERC20 поможет Вам принять правильное решение при выборе места хранения Ваших токенов на основе Ethereum.
Мы бы хотели услышать Ваш опыт, если Вы использовали какой-либо из вышеуказанных кошельков или любой другой кошелек ERC20.
Как хранить биткоины, альткоины и токены ERC-20 на Ledger Nano S
Введение
Ledger Nano S — замечательный аппаратный кошелек, который можно использовать для хранения альткоинов, ERC-20 и, конечно же, биткоинов.
Это пошаговое руководство поможет вам разобраться в настройке кошелька для различных валют. Но для начала не забудьте произвести первичную настройку гаджета — гайд вы найдёте на нашем сайте Настройка Ledger Nano S
Полный список поддерживаемых криптовалют
- Ark.
- Bitcoin.
- Bitcoin Cash.
- Dash.
- Dogecoin.
- Ethereum.
- Ethereum Classic.
- Komodo.
- Litecoin.
- PoSW.
- Ripple.
- Stratis.
- Zcash.
Кроме того, вы можете хранить в кошельке любые токены ERC-20 на базе Ethereum!
Чтобы начать работу
- Перейдите на сайт Ledger и найдите приложение «Ledger Manager». Возможно, вам придется скачать две версии программ «Wallet» и «Manager», в зависимости от монеты, которую вы хотите хранить.
- Ledger предоставляет три приложения для кошельков. Одно предназначено для Ripple, другое — для Ethereum, третье — для биткоинов и всего остального.
- Новичков может запутать, что Ledger заставляет вас использовать приложение «Bitcoin Wallet» для управления альткоинами, такими как ZCash или Litecoin. Скачайте нужную программу.
- Затем вам нужно загрузить правильное приложение «Manager». Если оно уже есть на устройстве — замечательно, если нет, то скачайте его.
- Как и приложение «Wallet», Ledger Manager будет доступен в качестве расширения для Chrome. Если вы вошли в свою учетную запись Google, программа будет сохранена в том же месте, что и «Bitcoin wallet», в разделе “Ваши приложения” в интернет-магазине Chrome. Обратите внимание, что «Manager» и «Wallet» не могут работать одновременно.
- Откройте «Ledger Manager» и нажмите на зеленую кнопку около монеты, которую вы хотите хранить на устройстве.
- Обратите внимание, что ТОЛЬКО 5 типов криптовалют могут одновременно храниться на Nano S, поэтому выбирайте внимательно. (Исключением являются все токены ERC-20 и Etherum — их можно хранить сколько угодно).
- Теперь, когда вы готовы, давайте посмотрим, как пользоваться «Ledger Bitcoin» для получения доступа к кошельку Litecoin.
Храните альткоины на Ledger Nano S
- Несмотря на то, что этот пример для Litecoin, вы можете выполнить те же шаги для других криптовалют, поддерживаемых Ledger Nano S. Единственное отличие — это версия приложения «Wallet».
- Помните, что есть отдельные расширения для Ripple, Ethereum, а программа для Биткоин позволяет работать и с альткоинами.
- Чтобы получить доступ к Litecoin, убедитесь, что у вас последняя версия приложения Litecoin, скачанная из «Ledger Manager». Затем, на главном экране Nano, листайте значки, пока не найдёте Litecoin — потом выберите его.
- После появится сообщение “Use wallet to view accounts”. Откройте свой биткоин- кошелек.
- На следующем экране обратите внимание, что Litecoin уже активировал «Segwit» во всей сети, поэтому на этом экране делать нечего. Если вы не знаете, что нажимать, выбирайте “I don’t know”.
- После того, как кошелек синхронизируется с сетью, он выведет вас на страницу, похожую на макет биткоин-кошелька.
- Фактически, она работает точно так же, как и кошелек, с такими же настройками на вкладке «Wallet’s Settings», включая «Display», «Coin», «Hardware», «Apps» (в Beta-версии), «Tools», и «Blockchains».
Поздравляем, теперь вы настроили свой кошелек Litecoin и готовы его использовать. Эти инструкции применимы и к другим монетам, просто выберите правильные приложения «Wallet» и «Manager».
Хранение токенов ERC-20 на Ledger Nano S
В Ledger Nano S нет приложений для кошельков, которые поддерживают токены ERC-20. Даже для Ethereum. Поэтому вам необходимо использовать сторонний кошелек для управления ERC-20.
Самое замечательное, что у MyEtherWallet есть интеграция с Ledger Nano S. Скорее всего, если вы уже участвуете в ICO и владеете токенами ERC-20, то знакомы с MyEtherWallet.
Итак, приступим
- Сначала перейдите на страницу https://www.myetherwallet.com/. Обратите внимание на “s” в конце «HTTPS:», что означает, что сайт защищен.
- Есть много фишинговых мошеннических порталов, которые выглядят точно так же, пытаясь обмануть вас и украсть приватные ключи. Поскольку Ledger Nano S уже подключен, выберите опцию аппаратного кошелька вверху.
- Затем подключите Ledger Nano S и нажмите на опцию “Ledger / TREZOR / Digital Bitbox” в верхнем правом углу.
- Выберите «Ledger Wallet».
- Прежде чем идти дальше, перейдите в настройки Ethereum на Nano S и выберите его.
- Затем перейдите на вкладку «Settings», где будет 2 темы: “Browser support” и “Contract data”.
- Выберите каждый из них и нажмите везде “Да”, что позволит MyEtherWallet получить доступ к Nano S.
Примечание: включение “Browser Support” не позволит работать приложению «Ledger Ethereum Wallet». Если вы когда-нибудь захотите его использовать просто переключите “Browser Support” на “No”.
- Включив эти функции, вернитесь в MyEtherWallet и нажмите кнопку «Connect to Ledger Wallet«.
- Появится всплывающий экран со множеством опций для различных криптовалют, которые могут потребоваться для заполнения кошельков.
- Также здесь есть несколько адресов кошельков, доступных на Nano S. Выберите опцию “Ledger (ETH)” и адрес.
- Нажав на один из адресов, вы попадете на этот экран.
- Выбранный адрес теперь используется, чтобы хранить токены ERC-20. Указывайте его, если вы участвуете в ICO и вам необходимо предоставить адрес кошелька ERC-20. Чтобы проверить баланс, нажмите на кнопку «Show Tokens«.
- Прежде чем вы увидите токен, вам понадобится контрактный адрес и десятичный код от компании, проводящей ICO. Обычно он предоставляется после ICO.
Вот и всё, теперь вы знаете, как хранить биткоины, альткоины и токены ERC-20 на Ledger Nano S! Если у вас его еще нет, то обязательно купите, чтобы в безопасности хранить свои сбережения.
Над статьями работает команда авторов, переводчиков и редактор. На сайте команда Privatefinance.biz публикует информационные статьи, обзоры, рейтинги, гайды о торговле на финансовых рынках и инвестировании, рекомендации по выбору брокера и инструментов инвестирования, актуальные новости из мира финансов.
Почта для связи с нами: [email protected]
Авторизация и аутентификация
Получить токен авторизации можно двумя способами: сгенерировать его в ЛК Модульбанка или получить по протоколу OAuth 2.
Генерация токена в ЛК
Если вы хотите получать от API данные исключительно по свой учетной записи в Модульбанке, воспользуйтесь механизмом получения токена в Личном кабинете. Выберите пункт «Подключиться к API» в меню действий ЛК и следуйте дальнейшим инструкциям.
Важно! Полученный токен привязан к вашей учетной записи в ЛК и не должен передаваться третьим лицам!
После генерации токена вы можете сразу начать его использование для получения данных в API.
Сгенерированный токен ничем не отличается от токена, полученного по протоколу OAuth.
OAuth 2. Общая схема работы
Если вы разрабатываете приложение (бот для телеграма, плагин для общедоступной CRM и т.д.), которое может быть полезно для любого пользователя Модульбанка, вы можете авторизовывать пользователей через сервер авторизации Модульбанка по OAuth подобному протоколу. Схема авторизации пользователей идентична протоколу OAuth 2.0, за небольшим исключением что сервер авторизации Модульбанка кроме формата x-www-form-urlencoded также поддерживает формат json в теле запроса. Для того чтобы стороннее приложение могло совершать запросы к API от лица конкретного пользователя, приложению необходимо получить токен авторизации, подтверждающий что пользователь предоставил приложению права на выполнение тех или иных действий.
Важно! Если вы хотите авторизовывать пользователей Модульбанка по протоколу OAuth, ваше приложение должно быть зарегистрировано у нас. Для регистрации приложения напишите нам письмо на [email protected]. В ответ мы вышлем вамclientId
и clientSecret
— уникальные для каждого приложения идентификатор и секретное слово (необходимые параметры для взаимодействия с сервером авторизации Модульбанка). Схема получения токена авторизации пользователя сторонним приложением.- Пользователь инициирует авторизацию стороннего приложения
- Приложение отправляет запрос Authorization Request на сервер авторизации Модульбанка
- Сервер авторизации Модульбанка перенаправляет пользователя на страницу авторизации
- Пользователь вводит свой логин и пароль, просматривает список запрашиваемых прав и подтверждает, либо отклоняет запрос авторизации.
- Приложение получает ответ Authorization Response в виде HTTP Redirect со временным токеном для получения доступа или кодом ошибки.
- Приложение, используя полученный временный токен доступа, отправляет запрос на получение токена авторизации
- Ответ содержит токен авторизации (
access_token
)
Запрос авторизации
Приложение отправляет запрос авторизации на сервер Модульбанка. Запрос авторизации отправляется из браузера клиента.
POST /v1/oauth/authorize HTTP/1.1
Host: api.modulbank.ru
Content-Type: application/json
Content-Length: <content-length>
Request body (в формате JSON):
{
redirectUri: '<страница приложения на которую будет отправлен пользователь после авторизации>',
clientId:'<ключ_приложения>',
scope:'account-info operation-history assistant-service',
state:'<данные этого параметра будут переданы на url возврата>'
}
Параметры запроса:
Параметры | Тип | Описание |
---|---|---|
clientId | string | Идентификатор приложения. Для получения идентификатора для приложения напишите нам на [email protected] |
state | string | параметр будет добавлен к redirectUri c тем же значением |
redirectUri | string | URI, на который сервер OAuth передает результат авторизации. Значение этого параметра при посимвольном сравнении должно быть идентично значению redirect_uri, указанному при регистрации приложения. При сравнении не учитываются индивидуальные параметры приложения, которые могут быть добавлены в конец строки URI. |
scope | string | Список запрашиваемых прав. Разделитель элементов списка — пробел. Элементы списка чувствительны к регистру. |
По запросу авторизации пользователь перенаправляется на страницы OAuth авторизации Модульбанка. Пользователь вводит свой логин и пароль, просматривает список запрашиваемых прав, подтверждает либо отклоняет запрос авторизации приложения. Результат авторизации возвращается как HTTP 302 Redirect. Приложение должно обработать ответ HTTP Redirect. Можно получить только одну авторизацию для одного пользователя. Повторная авторизация (с тем же значением параметра clientId) аннулирует выданные ранее разрешения. Параметры перенаправления с результатом авторизации:
Параметры | Тип | Описание |
---|---|---|
code | string | Временный токен (authorization code), подлежащий обмену на постоянный токен авторизации. Присутствует если пользователь подтвердил авторизацию приложения |
error | string | Код ошибки. Присутствует в случае ошибки или отказа в авторизации пользователем |
description | string | Дополнительное текстовое пояснение ошибки |
state | string | Транслируется из метода выше, если был передан |
Возможные ошибки:
Значение поля error | Описание |
---|---|
invalid_request | В запросе отсутствуют обязательные параметры, либо параметры имеют некорректные или недопустимые значения. |
invalid_scope | Параметр scope отсутствует, либо имеет некорректное значение или имеет логические противоречия. |
unauthorized_client | Неверное значение параметра client_id, либо приложение заблокировано |
access_denied | Пользователь отклонил запрос авторизации приложения. |
Пример ответа при успешной авторизации:
HTTP/1.1 302 Found
Location: https://your.app.com/?code=wovmrpbe0fgmskt
Ответ при отказе в авторизации:
HTTP/1.1 302 Found
Location: https://your.app.com/?error=access_denied
Обмен временного токена на токен авторизации
Временный токен (значение поля code ответа) подлежит немедленному обмену на токен авторизации. Время действия этого токена — меньше 1 минуты. Приложение должно получить и обработать ответ сервера и немедленно самостоятельно обменять временный токен на токен авторизации. Если приложению не удалось получить ответ сервера, временный токен утерян, либо срок его действия истек, необходимо повторить процедуру авторизации. Если авторизация завершилась успехом, приложение должно немедленно обменять временный токен на токен авторизации. Для этого необходимо отправить запрос, содержащий временный токен, на сервер авторизации Модульбанка. Запрос должен быть отправлен методом POST.
Формат запроса:
POST /v1/oauth/token HTTP/1.1
Host: api.modulbank.ru
Content-Type: application/json
Content-Length: <content-length>
Request body (в формате JSON):
{
"clientId":"<ключ_приложения>",
"code":"z43qjxtwwxsvk4cl3vtmvo",
"clientSecret":"секретный_ключ приложения",
}
Параметры запроса:
Параметры | Тип | Описание |
---|---|---|
code | string | Временный токен (authorization code) |
clientId | string | Идентификатор приложения, полученный при регистрации |
clientSecret | string | Секретное слово для проверки подлинности приложения |
В ответ на запрос сервер Модульбанка возвращает токен авторизации (accessToken), который является симметричным секретом приложения и дает право проводить операции со счетом пользователя. Токен возвращается в виде JSON-документа, который (в зависимости от результата обмена) может содержать одно из следующих полей:
Параметры | Тип | Описание |
---|---|---|
accessToken | string | Токен авторизации. Присутствует в случае успеха |
error | string | Код ошибки. Присутствует в случае ошибки |
Возможные ошибки:
Значение поля error | Описание |
---|---|
invalid_request | Обязательные параметры запроса отсутствуют или имеют некорректные или недопустимые значения |
unauthorized_client | Неверное значение параметра client_id или client_secret, либо приложение заблокировано |
invalid_grant | В выдаче access_token отказано. Временный токен не выдавался Модульбанком, либо просрочен, либо по этому временному токену уже выдан access_token (повторный запрос токена авторизации с тем же временным токеном) |
Пример ответа при успешном обмене временного токена:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 293
Cache-Control: no-store
{
"access_token":"aWQwMDAwMDAwMC0wMDAwLTAwMDAtMDAwMC0wMDAwMDAwMDAwMDA3MTQ5M2FhYy1lZTFjLTQ1ZWMtYTZkNC1kNTk4ZTQzM2NjNmY"
}
Пример ответа при ошибке:
HTTP/1.1 400 Bad Request
Content-Type: application/json
Content-Length: 25
Cache-Control: no-store
{
"error":"invalid_grant"
}
Использовать временный токен можно только один раз. Если приложению не удалось получить ответ сервера за время жизни временного токена, процедуру авторизации следует повторить сначала. Внимание! Полученный accessToken является симметричным секретом авторизации, поэтому разработчик приложения должен предпринять меры по его защите: хранить токен в зашифрованном виде, предоставлять доступ к нему только после авторизации пользователя в приложении. Срок действия токена 3 года. По истечении этого времени, токен автоматически аннулируется.
Отзыв токена
Приложение может отозвать полученный токен авторизации. Для отзыва токена отправьте следующий запрос на сервер авторизации:
POST /v1/revoke HTTP/1.1
Host: api.modulbank.ru
Content-Type: application/json
Authorization: Bearer <токен который необходимо отозвать>
Пример успешного ответа:
HTTP/1.1 200 OK
Content-Length: 0
Права на выполнение операций
При запросе авторизации стороннее приложение должно явно указывать в параметре scope набор прав, необходимых приложению для работы.
Список возможных прав:
Название права | Описание |
---|---|
account-info | Получение информации о компаниях пользователя (один и тот же клиент Модульбанка может быть сотрудником нескольких компаний) и счетах компаний пользователя |
operation-history | Просмотр истории операций |
operation-upload | Загрузка операций в ЛК |
Дайджест. Где хранить токены BEP-20, противостояние Binance и регуляторов, поиск криптосотрудников
Подборка актуальных событий для нашего сообщества.
Токены BEP-20 можно хранить в Ledger
Аппаратный кошелек Ledger добавил поддержку токенов (BEP-20), созданных на блокчейне Binance Smart Chain, а также нативную монету биржи Binance (BNB).
Это открывает больше возможностей для пользователей токенов EDCB стандарта BEP-20. Вы можете хранить свои токены как в официальных кошельках EDC Blockchain, которые практически не подвержены хакерским атакам за счет использования механизма консенсуса PoS и привлечения валидаторов, так и на холодных кошельках Ledger, не требующих постоянного интернет-соединения.
Завершен своп на EDCB (BEP-20) в EDC Blockchain
Осуществлена конвертация всех пользовательских токенов EDC (ERC-20) на токены EDCB (BEP-20) в системе EDC Blockchain. Миграция на новый стандарт BEP-20 в связи с подорожанием газа Ethereum позволяет пользователям осуществлять более быстрые транзакции с токеном EDCB и экономить на комиссиях. Вы можете также хранить монету BNB в кошельке EDC Blockchain и оплачивать газ в BNB при транзакциях с токенами.
Binance выполнили требования регулятора, но что дальше?
В конце июня этого года центральный орган надзора за рынком финансовых услуг Великобритании (FCA) предъявил ряд требований британскому подразделению биржи Binance, запретив вести деятельность в Великобритании. 25 августа FCA заявили без уточнения деталей, что Binance выполнили все требования регулятора.
Binance пришлось пересмотреть свои услуги, чтобы соответствовать условиям регуляторов, а также нанять нескольких бывших государственных и регуляторных чиновников на руководящие должности и ужесточить требования верификации на бирже. С конца августа новые клиенты должны будут предоставить удостоверение личности и пройти промежуточную верификацию.
Walmart в поисках криптоспециалистов
Вслед за онлайн-ритейлером Amazon управляющая сетью гипермаркетов корпорация Walmart опубликовала вакансию руководителя по криптопродуктам, который разработает стратегию развития в сфере цифровых валют и выведет компанию в лидеры в этом сегменте. Также в этом месяце сообщили о поиске криптоспециалистов британский конгломерат Lloyds Banking Group и управление военной разведки Израиля Моссад.
Криптовалюты и блокчейн уже не воспринимаются чем-то необычным, как это было несколько лет назад. Вместе с расширением индустрии блокчейн и спросом на криптоэкспертов увеличился порог входа в индустрию. Еще 4 года назад порог входа на рынок биткоина составлял $1000 в среднем, а сейчас необходимая сумма увеличилась в 5-10 раз. Однако все, кто приобрел биткоины в 2017 году и сумели сохранить их до 2021 года, увеличили свой доход в десятки раз.
EDC Blockchain занимается разработкой блокчейн-продуктов, пользоваться которыми может любой человек, независимо от его материального положения. Наоборот, используя новые цифровые разработки платформы, вы можете увеличивать свой уровень жизни: стекать EDC-монеты, зарабатывая ежедневный бонус, увеличивать оборот своей компании и нанимать сотрудников, выплачивая бонусы монетами, стать валидатором, поддерживающим сеть, и принимать участие в развитии комьюнити в 57 странах мира.
Криптовалюты и блокчейн – одни из самых растущих технологических секторов и имеют не меньшие перспективы, чем колонизация Марса, искусственный интеллект, запуск дронов и машины с автопилотом.
В технологическое будущее вместе с EDC Blockchain!
Подписывайтесь на каналы EDC Blockchain Telegram, Facebook и Twitter, чтобы отслеживать актуальные новости.
EDC Blockchain никогда не призывает к инвестиционной деятельности. Материалы, представленные на сайте, несут ознакомительный характер.
Аутентификация JWT: передовой опыт и когда его использовать
Примечание редактора : это руководство по аутентификации JWT последний раз обновлялось 1 июля 2021 года. Оно все еще может содержать устаревшую информацию.
В этом руководстве по аутентификации JWT вы узнаете, когда использовать JWT, почему не следует использовать JWT для сеансов и как хранить JWT в файлах cookie для предотвращения проблем с безопасностью. Мы также рассмотрим некоторые общие передовые методы работы с JWT.
Вот что мы расскажем:
JSON Web Tokens (JWT) — это представление заявки или заявок в формате JSON, которые могут передаваться между двумя сторонами.
Хотя это очень популярная технология, аутентификация JWT вызывает споры. Некоторые говорят, что вам никогда не следует его использовать. Другие говорят, что аутентификация JWT — это потрясающе.
Истина находится где-то посередине: ценность использования JWT зависит от вашего варианта использования и требований проекта.
Прежде чем копать глубже, давайте кратко рассмотрим, что такое аутентификация JWT.
Что такое JWT?
JWT — это механизм проверки владельца некоторых данных JSON. Это закодированная, безопасная для URL-адресов строка, которая может содержать неограниченное количество данных (в отличие от файлов cookie) и имеет криптографическую подпись.
Когда сервер получает JWT, он может гарантировать, что содержащимся в нем данным можно доверять, поскольку они подписаны источником. Ни один посредник не может изменить JWT после его отправки.
Важно отметить, что JWT гарантирует право собственности на данные, но не гарантирует шифрование. Данные JSON, которые вы храните в JWT, может увидеть любой, кто перехватывает токен, потому что он просто сериализован, а не зашифрован.
По этой причине настоятельно рекомендуется использовать HTTPS с JWT (и, кстати, HTTPS в целом).
Мы не собираемся подробно описывать, как генерируются JWT. Для более подробного и актуального взгляда на то, как работает аутентификация JWT, ознакомьтесь с разделом «Аутентификация JWT с нуля с помощью Vue.js и Node.js.»
Когда использовать JWT-аутентификацию
JWT — это особенно полезная технология для аутентификации API и межсерверной авторизации.
Подробное руководство по использованию технологии JWT для аутентификации API можно найти в статье «Как защитить REST API с помощью JWT».
Почему не следует использовать JWT в качестве токенов сеанса
С другой стороны, вы не должны использовать JWT в качестве токенов сеанса по умолчанию.Во-первых, JWT имеет широкий спектр функций и большой объем, что увеличивает вероятность ошибок как со стороны авторов библиотеки, так и со стороны пользователей.
Другая проблема заключается в том, что вы не можете удалить JWT в конце сеанса, потому что он самодостаточен и нет центрального органа, который мог бы их аннулировать.
Наконец, попросту говоря, JWT относительно велики. При использовании с файлами cookie это приводит к огромным накладным расходам на запрос.
Использование JWT для токенов сеанса поначалу может показаться хорошей идеей, потому что:
- На клиенте можно хранить любые данные о пользователях
- Сервер может доверять клиенту, потому что JWT подписан, и нет необходимости вызывать базу данных для получения информации, которую вы уже сохранили в JWT
- Вам не нужно координировать сеансы в централизованной базе данных, когда вы дойдете до возможной проблемы горизонтального масштабирования.
В конечном итоге, если у вас уже есть база данных для вашего приложения, просто используйте таблицу сеансов и используйте обычные сеансы, как это предусмотрено выбранной серверной структурой.
Почему? Использование JWT связано с определенными расходами: они отправляются для каждого запроса на сервер, и это всегда высокая стоимость по сравнению с сеансами на стороне сервера.
Кроме того, хотя риски безопасности при отправке JWT с использованием HTTPS сведены к минимуму, всегда существует вероятность того, что он будет перехвачен, а данные расшифрованы, что приведет к раскрытию ваших пользовательских данных.
Использование JWT для аутентификации API
Очень распространенное использование JWT — и, возможно, единственное хорошее — в качестве механизма аутентификации API.
ТехнологияJWT настолько популярна и широко используется, что Google использует ее, чтобы позволить вам аутентифицироваться в своих API.
Идея проста: вы получаете секретный токен от сервиса при настройке API:
На стороне клиента вы создаете токен (для этого существует множество библиотек), используя секретный токен для его подписи.
Когда вы передаете его как часть запроса API, сервер будет знать, что это конкретный клиент, потому что запрос подписан его уникальным идентификатором:
Как истечь срок действия одного токена JWT
Как сделать один токен недействительным? Легкое решение — изменить секретный ключ сервера, который делает недействительными все токены.Однако это не идеально для пользователей, у которых срок действия токенов может быть истек без причины.
Один из способов сделать это — добавить свойство к объекту пользователя в базе данных сервера, которое будет ссылаться на дату и время создания токена.
Маркер автоматически сохраняет это значение в свойстве iat
. Каждый раз, когда вы проверяете токен, вы можете сравнивать его значение iat
с серверным свойством пользователя
.
Чтобы сделать токен недействительным, просто обновите значение на стороне сервера.Если iat
старше этого, вы можете отклонить токен.
Другой способ добиться этого — создать черный список в вашей базе данных, кэшированный в памяти (или, что еще лучше, белый список).
Как безопасно хранить JWT в файле cookie
JWT должен храниться в безопасном месте в браузере пользователя. Если вы сохраните его в localStorage, он будет доступен любым скриптом на вашей странице. Это так же плохо, как кажется; атака XSS может дать доступ к токену внешнему злоумышленнику.
Повторяю, что бы вы ни делали, не храните JWT в локальном хранилище (или хранилище сеансов). Если какой-либо из сторонних скриптов, которые вы включаете на свою страницу, будет скомпрометирован, он получит доступ ко всем токенам ваших пользователей.
Чтобы обеспечить их безопасность, вы всегда должны хранить JWT внутри файла cookie httpOnly. Это особый вид файлов cookie, которые отправляются на сервер только в HTTP-запросах. Он никогда не доступен (как для чтения, так и для записи) из JavaScript, запущенного в браузере.
Использование JWT для аутентификации SPA
JWT могут использоваться как механизм аутентификации, не требующий базы данных.Сервер может избежать использования базы данных, потому что хранилище данных в JWT, отправленном клиенту, безопасно.
Использование JWT для авторизации операций на серверах
Допустим, у вас есть один сервер, на котором вы вошли в систему, SERVER1, который перенаправляет вас на другой сервер SERVER2 для выполнения какой-либо операции.
SERVER1 может выдать вам JWT, который авторизует вас на SERVER2. Этим двум серверам не нужно совместно использовать сеанс или что-либо еще для вашей аутентификации. Токен идеально подходит для этого варианта использования.
Как выбрать лучшую библиотеку JWT
Как вы решаете, какую библиотеку JWT использовать в своем проекте? Хорошее место для начала — это список библиотек JWT для подписи и проверки токенов.
Сайт содержит список самых популярных библиотек, реализующих JWT, включая библиотеки для Node.js, Python, Rust, Go, JavaScript и многих других.
Выберите нужный язык и выберите библиотеку, которую вы предпочитаете — в идеале, ту, которая имеет наибольшее количество зеленых флажков.
Заключение
JWT — очень популярный стандарт, который можно использовать для доверия запросам с помощью подписей и обмена информацией между сторонами. Убедитесь, что вы знаете, когда его лучше всего использовать, когда лучше использовать что-то еще и как предотвратить основные проблемы с безопасностью.
LogRocket: полная видимость ваших веб-приложений
LogRocket — это решение для мониторинга внешних приложений, которое позволяет воспроизводить проблемы, как если бы они произошли в вашем собственном браузере.Вместо того, чтобы угадывать, почему происходят ошибки, или запрашивать у пользователей снимки экрана и дампы журнала, LogRocket позволяет воспроизвести сеанс, чтобы быстро понять, что пошло не так. Он отлично работает с любым приложением, независимо от фреймворка, и имеет плагины для регистрации дополнительного контекста из Redux, Vuex и @ ngrx / store.
Помимо регистрации действий и состояния Redux, LogRocket записывает журналы консоли, ошибки JavaScript, трассировки стека, сетевые запросы / ответы с заголовками и телами, метаданные браузера и пользовательские журналы.Он также использует DOM для записи HTML и CSS на странице, воссоздавая видео с идеальным пикселем даже для самых сложных одностраничных приложений.
Попробуй бесплатно.Token Storage
Защита SPA, выполняющих вызовы API, связана со своими собственными проблемами. Вам необходимо убедиться, что токены и другие конфиденциальные данные не уязвимы для межсайтовых сценариев (XSS) и не могут быть прочитаны вредоносным JavaScript.
Чтобы узнать больше, см. Справочник JWT и Полное руководство к Next.js Аутентификация с Auth0.
Когда вы создаете приложение Next.js, аутентификация может потребоваться в следующих случаях:
При доступе к странице
При доступе к маршруту API
Когда ваше приложение вызывает API, размещенный вне вашего приложения Next.js от имени пользователя
Если сервер доступен, ваше приложение может обрабатывать взаимодействие с Auth0 и создавать сеанс, но в этой модели у нас нет серверной части.Вся работа происходит в интерфейсе:
Пользователь перенаправляется на Auth0.
Когда пользователь успешно вошел в систему, он будет перенаправлен обратно в приложение.
Клиентская сторона завершит обмен кодом с Auth0 и получит идентификатор пользователя
id_token
иaccess_token
, которые будут сохранены в памяти.
Если ваше приложение использует сценарий входа, который не требует вызовов API, требуется только токен идентификатора.Нет необходимости хранить его. Вы можете проверить его и получить из него необходимые данные.
Если вашему приложению необходимо вызывать API от имени пользователя, необходимы маркеры доступа и (необязательно) маркеры обновления. Они могут храниться на стороне сервера или в файле cookie сеанса. Файл cookie должен быть зашифрован и иметь максимальный размер 4 КБ. Если сохраняемые данные имеют большой размер, сохранение токенов в cookie сеанса нецелесообразно.
Используйте следующие типы потоков в этих сценариях:
Храните токены в защищенном хранилище, которое предлагает ОС, и ограничивайте доступ к этому хранилищу.Например, используйте KeyStore для Android и KeyChain для iOS.
Используйте следующие типы потоков в этих сценариях:
Мы рекомендуем использовать Auth0 SPA SDK для управления хранилищем токенов, управления сеансами и других деталей.
Когда SPA вызывает только API, обслуживаемый из домена, который может совместно использовать файлы cookie с доменом SPA, токены не требуются. OAuth добавляет дополнительные векторы атаки, не предоставляя никакой дополнительной ценности, и его следует избегать в пользу традиционного подхода на основе файлов cookie.
Когда SPA вызывает несколько API, которые находятся в другом домене, требуются токены доступа и, при необходимости, обновления.
Если бэкэнд SPA может обрабатывать вызовы API, обрабатывать токены на стороне сервера, используя:
Если бэкэнд SPA не может обрабатывать вызовы API, токены должны храниться в бэкэнде SPA, но SPA необходимо получить токены из серверной части для выполнения запросов к API. Между серверной частью и SPA необходимо установить протокол, чтобы обеспечить безопасную передачу токена от серверной части к SPA.
Если у вас есть SPA с и соответствующим внутренним сервером , ваш SPA должен запрашивать новые токены при входе в систему и сохранять их в памяти без сохранения. Затем для выполнения вызовов API ваш SPA будет использовать копию токена в памяти.
В соответствии со спецификациями OAuth3, когда браузер запрашивает токен обновления от конечной точки / token, Auth0 возвращает токен обновления только в том случае, если для этого клиента включена ротация токенов обновления.
Подробнее см. Auth0 SPA SDK в GitHub.
Auth0 рекомендует хранить токены в памяти браузера как наиболее безопасный вариант. Использование Web Workers для обработки передачи и хранения токенов — лучший способ защитить токены, поскольку Web Workers работают в отдельной глобальной области, чем остальная часть приложения. Используйте Auth0 SPA SDK, для которого по умолчанию используется хранилище в памяти с использованием веб-воркеров.
Если вы не можете использовать Web Workers, Auth0 рекомендует в качестве альтернативы использовать закрытие JavaScript для имитации частных методов.
Используйте Auth0 SPA SDK, для которого по умолчанию используется хранилище в памяти, чтобы использовать закрытие веб-воркеров и JavaScript в зависимости от типа токена.
Метод для хранения в памяти браузера не обеспечивает постоянство при обновлении страниц и вкладках браузера.
Использование локального хранилища браузера может быть жизнеспособной альтернативой механизмам, требующим получения токена доступа из iframe, и аутентификации на основе файлов cookie между доменами, когда это невозможно из-за ограничений браузера (например, ITP2).
Хранение токенов в локальном хранилище браузера обеспечивает постоянство при обновлении страниц и на вкладках браузера, однако, если злоумышленник может запустить JavaScript в SPA с помощью атаки межсайтового скриптинга (XSS), он может получить токены, хранящиеся в локальном хранилище. Уязвимость, ведущая к успешной атаке XSS, может быть либо в исходном коде SPA, либо в любом стороннем коде JavaScript (например, bootstrap, jQuery или Google Analytics), включенном в SPA.
Чтобы снизить риски безопасности, если ваш SPA использует неявные (мы рекомендуем вместо этого использовать поток кода авторизации с PKCE) или гибридные потоки, вы можете уменьшить абсолютное время истечения срока действия токена.Это снижает влияние отраженной XSS-атаки (но не постоянной). Чтобы сократить время истечения срока, перейдите на панель инструментов > API> Настройки> Срок действия токена для потоков браузера (секунды) .
Уменьшите количество стороннего кода JavaScript, включенного из источника за пределами вашего домена, до минимально необходимого (например, ссылок на jQuery, Bootstrap, Google Analytics и т. Д.). Сокращение количества стороннего кода JS снижает вероятность уязвимости XSS. Выполнение проверки целостности субресурсов (SRI) в сторонних сценариях (где это возможно) для проверки того, что извлеченные ресурсы доставляются без неожиданных манипуляций, также является более безопасным.
Руководство для каждой модели развертывания
Next.js — это минималистичный фреймворк для создания одностраничных приложений JavaScript простым, но настраиваемым способом. Фреймворк ориентирован на производительность и готовую поддержку рендеринга на стороне сервера (SSR). Витрина Next.js подтверждает успех фреймворка, который большие и малые компании используют для создания своих приложений, включая Netflix, Scale.ai, Marvel, Jet и даже Auth0.
Если вы новичок в Next.js и хотите узнать, как использовать этот фреймворк для создания приложений Jamstack с полным стеком, ознакомьтесь с видео-плейлистом Джеймса Куика, приведенным ниже:
Предоставление решения для поддержки аутентификации в Next.js была одной из самых востребованных функций платформы. Но почему так?
Разве мы не можем использовать какой-либо из инструментов, которые мы так долго использовали в React и Node.js, например, паспорт
или auth0.js
? Или новые, такие как Auth0 React SDK или Express OpenID Connect?
Next.js стирает грань между внешним и внутренним интерфейсом, делая существующую экосистему неоптимальной, если вы хотите использовать Next.js в полной мере.
Одним из примеров является Passport, который зависит от доступности Express.И хотя технически вы можете использовать Express в своем приложении Next.js, все улучшения производительности исчезнут. Если вы хотите оптимизировать для быстрого холодного запуска и повысить надежность и масштабируемость вашего приложения, вам необходимо перейти на модель бессерверного развертывания.
Существуют разные способы создания и развертывания приложений Next.js. В этом сообщении блога мы рассмотрим эти варианты использования Next.js, объясним их архитектуру и определим стратегию, которую вы можете использовать для реализации аутентификации для каждого из них.
Что означает аутентификация для Next.js?
При создании приложения Next.js аутентификация может потребоваться в следующих случаях:
При доступе к странице: «Мои счета»
При доступе к маршруту API Next.js:
/ api / my / invoices
Когда ваше приложение вызывает API, размещенный вне вашего приложения Next.js, от имени пользователя: с
www.mycompany.com
на выставление счетов.mycompany.com/api
Теперь, когда мы понимаем, где и когда нашему приложению может потребоваться аутентификация, давайте рассмотрим стратегии аутентификации, которые вы можете реализовать для различных моделей развертывания Next.js.
Next.js Подход к статическому сайту
Next.js позволяет создавать автономные статические приложения без необходимости в сервере Node.js. Вы можете запустить команду next build && next export
, чтобы сгенерировать файлы HTML для каждой страницы, которая ее поддерживает.Вы можете использовать этот сгенерированный вывод для развертывания своего сайта в любой службе статического хостинга, такой как Vercel, Amazon S3 или Netlify.
Вы можете использовать этот метод для создания полных веб-сайтов в виде статических сайтов, таких как общедоступная главная страница компании или когда вы создаете «панель администратора». Сгенерированный HTML может быть оболочкой вашего приложения — подумайте об этой оболочке как о верхнем и нижнем колонтитулах вашего приложения. Панель управления Vercel — один из лучших примеров того, как это может выглядеть:
После того, как «оболочка» будет обслужена, клиентская сторона вызовет необходимые API-интерфейсы (несущие информацию о пользователе), извлечет данные для конкретного пользователя. content, и обновите страницу:
Эта модель имеет ряд преимуществ, когда речь идет о хостинге.Сайты статического хостинга (такие как Vercel, Amazon S3, Azure Blob Storage, Netlify и другие) проверены на практике, недороги, но, что более важно, они очень быстрые и хорошо работают с CDN.
Одна вещь, которая будет несколько отличаться, — это то, как мы обрабатываем аутентификацию. Модель, в которой доступен сервер, может обрабатывать взаимодействие с Auth0 и создавать сеанс, но в этой модели у нас нет серверной части. Вся работа происходит во внешнем интерфейсе:
- Ваш статический сайт перенаправляет ваших пользователей на Auth0 для входа в систему.
- Когда ваши пользователи успешно входят в систему, Auth0 перенаправляет их на ваш статический сайт.
- Ваш статический сайт выполняет обмен кодом с Auth0 для получения идентификатора пользователя
id_token
иaccess_token
, которые он хранит в памяти.
Если для вашего варианта использования требуется динамический контент или пользовательский контент, вам также потребуется развернуть что-то еще, например API. Этот API не будет работать как часть вашего статического хостинга. Для ее развертывания вы будете использовать такую платформу, как AWS Lambda, Heroku или Now.Ваш статический сайт (на стороне клиента) будет использовать access_token
для безопасных вызовов этого API напрямую, получения динамического контента и обогащения статической страницы, обслуживаемой платформой хостинга.
Эта архитектура аналогична тому, как вы можете создать любое одностраничное приложение, в котором приложение не имеет фактического «бэкэнда», а вместо этого вызывает один или несколько API. В сообществе вы найдете множество примеров того, как войти в этот тип приложения:
Например, с auth0-react
это так же просто, как настроить ваше приложение следующим образом:
импортировать {Auth0Provider} из '@ auth0 / auth0-response';
экспорт класса по умолчанию Root extends App {
оказывать () {
const {Component, pageProps} = это.реквизит;
возвращение (
<Компонент {... pageProps} />
);
}
}
Затем вы можете использовать React Hooks для получения информации профиля пользователя и запроса токена доступа для безопасных вызовов ваших API. Ваш статический сайт Next.js отправляет access_token
в заголовках авторизации ваших вызовов API, что в следующем примере выполняется с помощью ловушки useSWR:
import {useAuth0} from '@ auth0 / auth0-response';
импортировать useSWR из swr;
экспортировать функцию по умолчанию MyShows () {
const {
Пользователь,
isAuthenticated,
isLoading,
getAccessTokenSilently,
} = useAuth0 ();
const {данные, ошибка} = useSWR (
isLoading || ! isAuthenticated? null: '/ api / my / shows',
async (url) => {
const accessToken = await getAccessTokenSilently ({
аудитория: 'https: // api / tv-show',
объем: 'читать: показывает',
});
const res = await fetch (url, {
заголовки: {
авторизация: `Bearer $ {accessToken}`,
},
});
вернуть res.json ();
}
);
if (isLoading) {
return Загрузка информации о пользователе ... ;
}
if (! isAuthenticated) {
return Вы должны сначала войти в систему, чтобы получить доступ к своим подпискам. ;
}
if (error) {
return При загрузке подписок произошла ошибка. ;
}
if (! data) {
возвращение (
Подписки на {user.email}
Загрузка подписок ...
);
}
возвращение (
Подписки для {пользователя.электронная почта}
Вы подписаны в общей сложности на шоу {data.length} ...
);
}
Посетите Практическое введение Next.js, чтобы узнать, как использовать среду Next.js для создания приложений React.
Что именно здесь происходит за кулисами?
При использовании auth0-spa-js
пользователь войдет в систему, используя предоставление кода авторизации с PKCE. На высоком уровне ваше приложение Next.js перенаправляет пользователя на Auth0 для входа в систему.Auth0 будет обрабатывать всю необходимую логику аутентификации и авторизации (регистрация, вход, MFA, согласие и т. Д.). После того, как пользователи завершат процесс аутентификации с помощью Auth0, Auth0 перенаправляет их в ваше приложение с кодом авторизации в строке запроса.
Клиентская сторона обменивает этот код на id_token
и, необязательно, на access_token
(1,2) . Вы можете использовать access_token
для вызова вашего API. Когда access_token
истечет, тот же поток повторится снова под крышками с использованием
.Этот подход «тихой аутентификации» будет работать до тех пор, пока пользователь вошел в систему — пока у пользователя есть сеанс в Auth0. Когда сеанс пользователя в Auth0 истекает или происходит выход, этот вызов завершится ошибкой, и пользователю потребуется снова войти в систему.
Next.js Модель бессерверного развертывания
Где Next.js сияет, так это в модели бессерверного развертывания, где вы развертываете все страницы и маршруты API как отдельные бессерверные функции, реализованные, например, с использованием Vercel или AWS Lambda.
В этой модели у вас не работает полноценная веб-платформа (например, Express.js), но вместо этого среда выполнения будет выполнять функции, передавая им запрос и объект ответа ( (req, res) = > {}
). Вот почему мы не можем использовать традиционные веб-фреймворки (например, Express.js) или какие-либо строительные блоки, которые они предлагают для аутентификации пользователей в этой модели (например, Passport.js) и создания сеансов ( экспресс-сеансов
).
На следующей схеме показано, как работает эта модель: Далее.js-страницы и маршруты API выполняются как отдельные бессерверные функции. Когда браузер пытается получить доступ к странице TV Shows (1) , функция позаботится о рендеринге и обслуживании страницы, эффективно выполняя рендеринг на стороне сервера. Эта функция также будет вызывать любые API-интерфейсы, необходимые странице для получения необходимых данных (2) .
Если весь сайт уже загружен, рендеринг происходит на клиенте всякий раз, когда вы посещаете другую страницу. В этот момент клиентское приложение выполняет все последующие вызовы API напрямую.Как видите, именно здесь граница между слоями внешнего интерфейса и внутреннего интерфейса начинает размываться.
Прежде чем мы углубимся в какие-либо детали, важно отметить, что существует две разновидности бессерверной модели, когда речь идет об аутентификации, в зависимости от того, где вам нужен доступ к пользователю.
Бессерверный с пользователем на внешнем интерфейсе
Один вариант, очень похожий на Static Site , показан на диаграмме ниже.Всякий раз, когда вам нужно отобразить страницу на стороне сервера или вызвать маршрут API, вы будете выполнять эти вызовы в бессерверной функции. В этой модели аутентификация происходит на стороне клиента:
- Клиентское приложение перенаправляет пользователя на Auth0.
- Когда пользователи успешно входят в систему, Auth0 перенаправляет их в клиентское приложение.
- Клиентское приложение завершает обмен кодом с Auth0 и извлекает пользовательские
id_token
иaccess_token
, которые оно сохраняет в памяти.
Любая страница, отображаемая бессерверной функцией, может возвращать только контент, к которому все пользователи могут получить доступ без какой-либо формы аутентификации. Когда ваше клиентское приложение загружает страницу, оно может выполнять некоторую логику для получения пользовательского контента, вызывая маршруты API или вызывая другие API.
На диаграмме выше вы можете увидеть пример того, как это может работать:
- Бессерверная функция (SSR) может отображать страницу
/ аккаунт
. - В свою очередь, эта бессерверная функция также вызывает маршрут API
/ api / pricing-tiers
, который просто возвращает различные типы подписки, доступные в приложении (например, Free, Developer, Enterprise). Это общедоступная информация, поэтому для доступа к данным о ценах аутентификация не требуется. - Когда клиентская сторона готова, она теперь может вызвать маршрут API
/ api / billing-info
и предоставить токен доступа пользователя. Затем клиентская сторона может отображать контент, специфичный для пользователя.Для доступа к платежной информации пользователя требуется аутентификация.
Только клиентская сторона и маршруты API знают о пользователе, в то время как рендеринг страниц на стороне сервера может отображать только общедоступный контент, что идеально подходит для целей SEO.
Бессерверная с пользователем на бэкэнде
Второй вариант в этой модели включает бессерверную функцию, которая требует от пользователя при рендеринге страницы. В таком случае нельзя полагаться только на аутентификацию на стороне клиента.
Эта диаграмма похожа на диаграмму из модели внешнего интерфейса, за исключением нескольких тонких, но важных отличий:
- Бессерверная функция (SSR) может отображать страницу
/ аккаунт
, но браузер отправляет файл cookie сеанса к нему. - Эта бессерверная функция может вызывать
/ api / billing-info
, пересылая файл cookie сеанса. Бессерверная функция теперь может отображать пользовательский контент. - Эта бессерверная функция также может вызывать маршрут API
/ api / pricing-tiers
(здесь ничего не меняется по сравнению с моделью внешнего интерфейса).
В этом примере сторона сервера может полностью отобразить страницу учетной записи пользователя.
Вам также необходимо рассмотреть случай, когда сайт уже полностью загружен, а пользователь переходит на страницу учетной записи. В этом случае клиентская сторона может напрямую вызывать конечные точки, и файл cookie будет автоматически предоставлен маршруту API:
- Клиентское приложение может вызвать маршрут API, требующий аутентификации (поскольку браузер автоматически предоставит файл cookie сеанса). ).
- Клиентское приложение также может вызывать маршруты API, не требующие аутентификации.
Чтобы учесть этот вариант использования, мы опубликовали @ auth0 / nextjs-auth0
, который обеспечивает аутентификацию в модели бессерверного развертывания с использованием предоставления кода авторизации. Этот пакет также создает сеанс для аутентифицированного пользователя с использованием файла cookie HttpOnly
, который смягчает наиболее распространенные атаки XSS.
Чтобы использовать библиотеку, вы начнете с определения некоторых переменных среды в файле .env.local
в корне вашего приложения:
AUTH0_SECRET = какой-то-очень-очень-очень-очень-очень-очень-очень-длинный-секрет
AUTH0_BASE_URL = http: // локальный: 3000
AUTH0_ISSUER_BASE_URL = https: //YOUR_AUTH0_DOMAIN.auth0.com
AUTH0_CLIENT_ID = ВАШ_AUTH0_CLIENT_ID
AUTH0_CLIENT_SECRET = YOUR_AUTH0_CLIENT_SECRET
Прочтите документ «Переменные среды» для получения дополнительных сведений о загрузке переменных среды в Next.js.
Вы можете выполнить следующую команду, чтобы легко сгенерировать подходящую строку для секрета сеанса:
node -e "console.log (crypto.randomBytes (32) .toString ('hex')) "
Затем создайте обработчик маршрута динамического API по адресу /pages/api/auth/[...auth0 impression.js
.
импортировать {handleAuth} из '@ auth0 / nextjs-auth0';
экспорт по умолчанию handleAuth ();
Это создаст следующие URL-адреса: / api / auth / login
, / api / auth / callback
, / api / auth / logout
и / api / auth / me
.
И все! Теперь вы настроили серверную часть своего приложения.
Чтобы настроить клиентскую часть, оберните компонент pages / _app.js
в компонент UserProvider
.
импортировать React из React;
импортировать {UserProvider} из '@ auth0 / nextjs-auth0';
экспортировать приложение функции по умолчанию ({Component, pageProps}) {
возвращение (
<Компонент {... pageProps} />
);
}
Теперь вы можете войти в систему, выйти из системы и получить доступ к пользователю на клиенте.
импортировать {useUser} из '@ auth0 / nextjs-auth0';
экспорт по умолчанию () => {
const {пользователь, ошибка, isLoading} = useUser ();
if (isLoading) return Загрузка... ;
если (ошибка) return {error.message} ;
if (user) {
возвращение (
Добро пожаловать, {user.name}! Выйти
);
}
вернуть логин ;
};
Обратите внимание, что в этой модели аутентификация происходит на сервере, а это означает, что клиент не знает, что пользователь вошел в систему. Хук useUser
информирует его, обращаясь к этой информации в исходном состоянии или через / api / auth / profile
, но он не будет предоставлять клиенту id_token
или access_token
.Эта информация остается на стороне сервера.
Что именно здесь происходит за занавесками?
При использовании nextjs-auth0
пользователь входит в систему, используя предоставление кода авторизации. На высоком уровне клиентское приложение перенаправляет пользователя на Auth0 (1,2) , который обрабатывает всю необходимую логику аутентификации и авторизации (регистрация, вход, MFA, согласие и т. Д.). После входа пользователей Auth0 перенаправляет их в ваше приложение с кодом авторизации в строке запроса (3) .
Сторона сервера (или, лучше, бессерверная функция) затем обменивает (4) этот код на id_token
и, необязательно, на access_token
и refresh_token
. После того, как библиотека проверит id_token
, она создает сеанс и сохраняет его в зашифрованном файле cookie (5) . Каждый раз, когда вы визуализируете страницу на стороне сервера или вызываете маршрут API, вы отправляете cookie сеанса бессерверным функциям, которые затем могут получить доступ к сеансу и любой соответствующей информации о пользователе.
Вызов внешнего API
Все страницы и маршруты API могут обращаться к сеансу пользователя, но это не относится к внешним API, обычно размещенным в других (под) доменах. При использовании этих API вам необходимо предоставить им access_token
, чтобы разрешить пользователю доступ к их защищенным ресурсам.
Когда вам нужно вызвать внешний API от имени пользователя, вы должны проксировать этот вызов через маршрут API Next.js. Эти маршруты будут иметь доступ к сеансу пользователя, и, в зависимости от того, как пользователь вошел в систему, этот сеанс может содержать информацию о пользователе.Необязательно, сеанс также может иметь следующее:
-
id_token
-
access_token
-
refresh_token
Когда маршрут API Next.js должен вызвать внешний API от имени пользователя, он может извлечь access_token
из сеанса и добавить его в заголовок Authorization
HTTP-вызова.
В следующем примере показано, как создать маршрут API, который извлекает access_token
из сеанса и затем использует его для вызова нижележащего API.
импорт {getAccessToken, withApiAuthRequired} из '@ auth0 / nextjs-auth0';
экспорт по умолчанию withApiAuthRequired (async function products (req, res) {
пытаться {
const {accessToken} = ждать getAccessToken (req, res);
const client = новый BillingApiClient (accessToken);
return client.getBillingInfo ();
} catch (ошибка) {
console.error (ошибка)
res.status (error.status || 500) .end (error.message)
}
});
Самое большое отличие от модели внешнего интерфейса состоит в том, что сервер будет знать статус аутентификации пользователя при рендеринге страниц.Таким образом, серверная сторона не будет ограничиваться загрузкой общедоступных данных. Сторона сервера также может загружать данные, специфичные для пользователя, и отображать эту информацию.
Вы можете найти полный пример Auth0 в официальном репозитории Next.js.
Индивидуальный серверный подход
Очень распространенная (но устаревшая) модель развертывания, которую вы увидите с Next.js, — это когда вы используете настраиваемый сервер для размещения приложения Next.js. Вы можете реализовать собственный сервер в Next.js, используя что-то вроде Express.js.Это работает так:
- Пользовательский сервер принимает запрос.
- Пользовательский сервер вызывает метод
app.getRequestHandler ()
, чтобы получить обработчик запроса Next.js. - Пользовательский сервер перенаправляет запрос обработчику запросов Next.js.
При таком подходе настраиваемый сервер может действовать как прокси и обрабатывать запрос до того, как Next.js обработает его:
Промежуточное ПО, которое запускается перед рендерингом на стороне сервера Next.js, предоставляет строительные блоки вашему приложению. например:
- Аутентификация
- Сессии
- Обеспечение аутентификации и авторизации
- Ограничение скорости
Все строительные блоки и инструменты, которые вы можете использовать сегодня с Express.js доступны в этой настраиваемой модели сервера. Вот самый простой пример размещения вашего приложения Next.js в Express.js:
const next = require ('next');
const express = require ('экспресс');
...
const app = next ({dev});
константный дескриптор = app.getRequestHandler ();
app.prepare ()
.then (() => {
const server = express ();
...
Паспорт. использование (auth0);
...
server.use (паспорт.initialize ());
server.use (паспорт.сессия ());
server.use (myApiRoutes);
...
server.get ('*', (req, res) => {
дескриптор возврата (req, res);
});
server.listen (3000, (ошибка) => {
if (err) {
бросить ошибку;
}
console.log ('Прослушивание http: // localhost: 3000')
});
})
.catch ((ex) => {
console.error (например, стек);
process.exit (1);
});
Когда дело доходит до аутентификации пользователей в пользовательской модели сервера, вы можете использовать Passport.js (который на сегодняшний день является самой популярной платформой для аутентификации в Node.js) в сочетании с паспортом-auth0
.Когда пользователь входит в систему, Passport.js создает сеанс с использованием экспресс-сеанса
и сохраняет его в браузере с помощью файла cookie HttpOnly
.
После того, как пользователь запустил сеанс, он может получить доступ к страницам или вызвать конечные точки API, требующие аутентификации, с использованием маршрутов API Next.js или традиционных конечных точек Express. Клиентское приложение отправляет файл cookie сеанса вместе с каждым запросом, что автоматически делает информацию пользователя доступной на стороне сервера.
В этой модели вы в основном используете Node.js и Express для создания обычного веб-приложения. Аутентификация, доступ к базе данных и другие функции — уже решенная проблема.
Посетите руководство по аутентификации Next.js, чтобы получить полный пример того, как создать приложение Next.js с использованием пользовательской модели сервера.
Устаревшая модель?
В документации Next.js эта модель больше не указана, потому что она наименее оптимальна с точки зрения стоимости и производительности:
- Вы упускаете преимущества модели бессерверного развертывания, такие как распределенные точки отказа, бесконечная масштабируемость , и невысокая стоимость.
- Вы не можете создавать статические сайты, которые могут вам понадобиться, если вы используете общедоступный веб-сайт. Статические сайты размещать быстро и недорого.
Заключение
Таким образом, мы рассмотрели различные модели развертывания, существующие сегодня для инфраструктуры Next.js, и объяснили лучший способ аутентификации в этих моделях и его обоснование.
Если это руководство помогло вам лучше решить, что использовать для вашей модели развертывания, сообщите нам об этом в комментариях ниже!
Об Auth0
Платформа Auth0 Identity Platform, подразделение Okta, использует современный подход к идентификации и позволяет организациям обеспечивать безопасный доступ к любому приложению для любого пользователя.Auth0 — это платформа с широкими возможностями настройки, которая настолько проста, насколько хотят команды разработчиков, и настолько гибкой, насколько им нужно. Защищая миллиарды транзакций входа в систему каждый месяц, Auth0 обеспечивает удобство, конфиденциальность и безопасность, поэтому клиенты могут сосредоточиться на инновациях. Для получения дополнительной информации посетите https://auth0.com.
Как безопасно хранить токены JWT.
Статья изначально опубликована здесь.
В последние годы токены JWT широко используются в качестве метода аутентификации и авторизации для веб-приложений.Они позволяют внутренним разработчикам аутентифицировать пользователей без единого запроса к серверу базы данных или любому другому типу хранилища. Они очень просты в использовании, и они также используют самый распространенный формат, который в настоящее время используется для данных в Интернете, JSON.
Из-за этих фактов растет число случаев, когда пользователи неправильно хранят токены JWT, что делает веб-приложения уязвимыми для различных видов атак.
Но сначала, что такое токен JWT?
JWT — это сокращение от JSON Web Token.JWT — это не что иное, как представление объекта JSON в формате base64 с криптографической подписью. Подписывая токен, мы убеждаемся, что его содержимое никоим образом не было изменено. Это достигается путем проверки полученного токена с тем же ключом, который использовался для его подписи в первую очередь. В случае, если генерируемая нами подпись не совпадает с подписью в токене, мы должны считать, что токен недействителен.
токенов JWT состоят из трех частей, представленных в виде строк base64:
Заголовок, который обычно содержит дату истечения срока действия токена, алгоритм, используемый для подписи, и дополнительные метаданные.
Полезная нагрузка JSON.
Подпись, созданная путем подписания заголовка и полезной нагрузки
Заголовок и полезные данные хранятся в формате JSON до подписания. Последний токен представляет собой конкатенацию вышеуказанных данных base64, разделенных точкой. Итак, токен JWT будет выглядеть следующим образом:
[заголовок]. [Полезная нагрузка]. [Подпись]
Теперь давайте посмотрим, как лучше всего хранить токен JWT.
Должен ли я хранить свой JWT в локальном хранилище?
Большинство людей склонны хранить свои JWT в локальном хранилище веб-браузера.Эта тактика оставляет ваши приложения открытыми для атаки под названием XSS. Мы будем обсуждать XSS только в контексте JWT, вы можете найти больше об этом здесь. В этом виде атаки злоумышленник использует тот факт, что локальное хранилище доступно для любого кода javascript, работающего в том же домене, что и веб-приложения. Так, например, если злоумышленник может найти способ злонамеренно внедрить код javascript в ваше приложение (путем внедрения кода в модуль узла, который вы используете, не зная об этом), ваш токен JWT немедленно становится доступным для их.
Итак, ответ на этот вопрос: Нет, никогда не храните JWT в локальном хранилище.
Но как насчет хранилища сеансов?
Хм, посмотрим, что будет в этом случае. Как и локальное хранилище, хранилище сеансов доступно для любого кода javascript, работающего в том же домене, где размещено веб-приложение. Таким образом, единственное, что изменится, — это то, что когда пользователь закроет свой браузер, JWT исчезнет, и пользователю придется снова войти в систему при следующем посещении вашего веб-приложения.
И снова ответ тот же: Никогда не храните JWT в хранилище сеансов.
Хорошо, но я всегда могу использовать память браузера, верно?
Конечно, если вы сделаете свой токен доступным только с помощью своего кода, это безопасное решение. Единственное предостережение: когда пользователь обновляет браузер, он должен снова войти в систему. Не так уж и круто, правда?
Я рекомендую использовать этот подход, когда пользователь по неизвестной причине ДОЛЖЕН снова войти в систему при обновлении браузера,
Но если я не могу использовать ни один из них, что тогда? Печенье? Файлы cookie такие 2010…
Перестаньте распускать куки, куки — это здорово.Мы используем их в течение многих лет, они автоматически отправляются в каждом запросе браузера (включая ajax, если мы этого хотим), и они СУПЕР БЕЗОПАСНОСТЬ !!!
Дальний голос: но файлы cookie также доступны через javascript.
Это правда, но только если на сервере не установлен флаг HttpOnly, который вы всегда должны устанавливать для файлов cookie аутентификации или авторизации. Такой далекий голос, мы согласны с этим?
Дистанционный голос: Конечно, нет, что, если кто-то отправит их через незащищенный HTTP-запрос?
Во-первых, в наши дни никто не должен использовать простой HTTP, но даже в этом случае мы можем установить флаг Secure при создании cookie, чтобы он никогда не отправлялся через незащищенное соединение.Думаю, можно двигаться дальше…
Далекий голос: Ты куда-то торопишься, братан? Вы забыли CSRF.
F @! K. Это правда, я забыл про CSRF-атаки. Итак, , что такое CSRF-атака ?
Атака CSRF выполняется, когда злоумышленник использует поведение браузера по умолчанию для отправки всех файлов cookie даже при междоменных запросах. При неправильном обращении это может привести к серьезным уязвимостям безопасности. Пример этой атаки следующий:
Злоумышленник отправляет электронное письмо с красивым предложением и добавляет кнопку CTA в конце: «ПОЛУЧИТЬ СКИДКУ 50%».
Пользователь в восторге от этого потрясающего предложения и нажимает кнопку.
На самом деле кнопка отправляет POST-форму вашему веб-приложению, а точнее конечной точке, которая меняет пароль пользователя на новый.
Поскольку файлы cookie отправляются в каждом запросе, даже в междоменном, конечная точка работает должным образом, если пользователь вошел в систему на более раннем этапе работы с вашим веб-приложением.
Теперь пользователь вышел из системы и больше не может входить в ваше веб-приложение.
Следует отметить, что эта атака будет выполнена злоумышленником, который просто хочет немного поиграть и проверить свои навыки. Можно было выполнить более серьезные операции, например, заставить пользователя перейти на очень дорогой тарифный план или даже перевести деньги со своего банковского счета на счет злоумышленника.
Так что я могу с этим поделать?
Первый вариант — просто забыть об этом, никогда никому не рассказывать и надеяться, что никто никогда не узнает (особенно злонамеренный хакер).Вы готовы к работе !!! Шучу…
Вы можете использовать токен, сгенерированный серверной частью, в каждом запросе, который вы выполняете к серверу (обычно в любом запросе POST, PUT, DELETE), поэтому, когда пользователь выполняет запрос, вы проверяете, действителен ли токен, извлекая его из некоторого кеша или даже прямо из базы. Но для этого требуется, чтобы вы создавали новый токен каждый раз, когда пользователь перенаправляется на новую страницу? Так есть ли альтернатива?
В течение многих лет, к сожалению, единственным способом обезопасить себя было использование токена CSRF при использовании аутентификации на основе файлов cookie.С 2016 года современные браузеры начали внедрять политику файлов cookie под названием SameSite. SameSite может принимать одно из трех значений:
.Каждый из них пригодится в своем деле.
Первый, None, позволяет отправлять cookie во всех возможных запросах, включая междоменные. Вот как браузеры много лет обрабатывали файлы cookie. Новое значение по умолчанию для SameSite в большинстве современных браузеров — Lax, хотя еще не все браузеры используют Lax в качестве политики файлов cookie SameSite по умолчанию.
Здесь вы можете найти информацию о совместимости браузеров.
Так что такое Лакс? Lax позволяет отправлять файлы cookie в междоменных запросах, если команда запроса GET. Все остальные запросы не будут содержать файлы cookie в соответствии с политикой Lax SameSite. Таким образом, он позволяет использовать файлы cookie, например, при перенаправлении пользователя с электронного письма на экран панели управления вашего приложения, но не позволяет вредоносной форме отправлять данные на конфиденциальную конечную точку.
Мы должны упомянуть, что Lax работает для всех запросов перенаправления GET.Он не будет отправлять файлы cookie в запросе ajax, поэтому никто не может просто добавить код на свой сайт и запросить, например, конечную точку / me , похитив личные данные пользователя, вошедшего в систему. Он также будет проигнорирован в случае iframe, даже для запросов перенаправления.
Итак, наиболее распространенными способами отправки Lax cookie из междоменного запроса GET являются следующие.
Пользователь нажимает ссылку, которая перенаправляет на ваш сайт
Пользователь отправляет запрос формы GET, который перенаправляет на ваш веб-сайт (полезно, если вы хотите предоставить способ передачи динамических аргументов в строку запроса с помощью формы с другого сайта)
Если команда типа window.location.href = ”yoursite…” используется .
Теперь политика Strict SameSite не позволяет каким-либо образом передавать cookie через междоменные запросы. Это может быть полезно в некоторых крайних случаях, но вы должны понимать, что даже простое перенаправление ссылки приведет к выходу вашего пользователя из вашего веб-приложения, если вы используете эту политику. Конечно, самый безопасный.
Итак, я просто использую Lax или Strict, и теперь я могу спать, не опасаясь CSRF или XSS-атаки.Верно?
Почти. Вы должны убедиться, что ваши пользователи используют современный браузер, поддерживающий такие функции. Если нет, лучше всего сообщить пользователю, что ваше приложение в настоящее время не поддерживается конкретной версией браузера и что ему следует перейти на более новую версию.
Если вы не используете подобное сообщение, есть вероятность, что сервер попытается установить политику SameSite, но браузер проигнорирует ее.Например, Internet Explorer не поддерживает такую функциональность. Если вам нужна явная поддержка старого браузера, вам следует вернуться к реализации токена CSRF.
Если вы нашли этот пост в блоге полезным, вы можете подписаться на мой информационный бюллетень и узнавать первыми о любых новых сообщениях.
Векторный фон, созданный vectorpocket — www.freepik.com
LocalStorage против файлов cookie: все, что вам нужно знать о безопасном хранении токенов JWT во внешнем интерфейсе
В моем последнем посте мы рассмотрели, как OAuth 2.0 работает и изучил, как генерировать токены доступа и обновлять токены. Теперь мы рассмотрим, как хранить токены в вашем интерфейсе.
Токены доступа обычно представляют собой недолговечные токены JWT, которые подписываются вашим сервером и включаются в каждый HTTP-запрос к вашему серверу для авторизации запроса. Токены обновления обычно представляют собой долговечные непрозрачные строки, которые хранятся в вашей базе данных и используются для получения нового токена доступа по истечении срока его действия.
Где мне хранить свои токены во внешнем интерфейсе?
Есть два распространенных способа хранения ваших жетонов.Первый находится в localStorage
, а второй — в файлах cookie. Существует много споров о том, какой из них лучше, и большинство людей склоняются к файлам cookie, поскольку они более безопасны.
Давайте проведем сравнение между localStorage
и файлами cookie. Эта статья в основном основана на этой статье и комментариях к этой публикации.
Локальное хранилище
Плюсы: Удобно.
- Это чистый JavaScript, и это удобно. Если у вас нет серверной части и вы полагаетесь на сторонний API, вы не всегда можете попросить сторонний API установить определенный файл cookie для вашего сайта.
- Работает с API, которые требуют, чтобы вы поместили ваш токен доступа в заголовок, например:
Носитель авторизации $ {access_token}
.
Минусы: уязвим для XSS-атак.
XSS-атака происходит, когда злоумышленник может запустить JavaScript на вашем веб-сайте. Это означает, что злоумышленник может забрать токен доступа, который вы сохранили в своем localStorage
. Атака XSS может происходить из стороннего кода JavaScript, включенного в ваш сайт, например React, Vue, jQuery, Google Analytics и т. Д.Практически невозможно не включить на свой сайт какие-либо сторонние библиотеки.
httpOnly Cookies
Плюсы: файл cookie недоступен через JavaScript; следовательно, он не так уязвим для XSS-атак, как localStorage
.
- Если вы используете
httpOnly
ибезопасные файлы cookie
, это означает, что к вашим файлам cookie нельзя получить доступ с помощью JavaScript, поэтому даже если злоумышленник может запустить JS на вашем сайте, он не сможет прочитать ваш токен доступа из файла cookie. . - Он автоматически отправляется в каждом HTTP-запросе на ваш сервер.
Минусы: в зависимости от варианта использования вы не сможете хранить свои токены в файлах cookie.
- Размер файлов cookie составляет 4 КБ. Поэтому, если вы используете большой токен JWT, сохранение в файле cookie не вариант.
- Существуют сценарии, в которых вы не можете поделиться файлами cookie со своим сервером API или API требует, чтобы вы поместили токен доступа в заголовок авторизации. В этом случае вы не сможете использовать файлы cookie для хранения своих токенов.
Об атаке XSS
Локальное хранилище уязвимо, потому что оно легко доступно с помощью JavaScript, и злоумышленник может получить ваш токен доступа и использовать его позже. Однако, хотя файлы cookie httpOnly
недоступны с помощью JavaScript, это не означает, что с помощью файлов cookie вы защищены от XSS-атак с использованием вашего токена доступа.
Если злоумышленник может запустить JavaScript в вашем приложении, он может просто отправить HTTP-запрос на ваш сервер, который автоматически включит ваши файлы cookie; Это просто менее удобно для злоумышленников, потому что они не могут прочитать содержимое токена, хотя им редко приходится.Для злоумышленника также может быть более выгодно атаковать с помощью браузера жертвы (просто отправив этот HTTP-запрос), а не с помощью машины злоумышленника.
Cookie-файлы и CSRF-атака
CSRF-атака — это атака, вынуждающая пользователя выполнить непреднамеренный запрос. Например, если веб-сайт принимает запрос на изменение адреса электронной почты через:
<> Копировать
POST / email / change HTTP / 1.1 Хост: site.com Тип содержимого: application / x-www-form-urlencoded Длина содержимого: 50 Cookie: session = abcdefghijklmnopqrstu email = myemail.example.com
Затем злоумышленник может легко создать форму
на вредоносном веб-сайте, который отправляет запрос POST на https://site.com/email/change
со скрытым полем электронной почты и файлом cookie сеанса
будут автоматически включены.
Однако это можно легко смягчить, используя флаг sameSite
в вашем файле cookie и включив токен анти-CSRF.
Cookie предпочтительнее по сравнению с localStorage
Хотя файлы cookie все еще имеют некоторые уязвимости, по возможности предпочтительнее, чем localStorage
.Почему?
- Как
localStorage,
, так и файлы cookie уязвимы для XSS-атак, но злоумышленнику сложнее выполнить атаку, если вы используетеhttpOnly
cookie. - Файлы cookie уязвимы для атак CSRF, но их можно смягчить с помощью флага
sameSite
и токенов анти-CSRF. - Вы все равно можете заставить его работать, даже если вам нужно использовать заголовок
Authorization: Bearer
или ваш JWT больше 4 КБ.
Это также согласуется с рекомендацией сообщества OWASP:
Не храните идентификаторы сеанса в локальном хранилище, поскольку данные всегда доступны с помощью JavaScript.Файлы cookie могут снизить этот риск с помощью флага httpOnly.
— OWASP: шпаргалка по безопасности HTML5
Итак, как мне использовать файлы cookie для сохранения моих токенов OAuth 2.0?
Напомним, вот различные способы хранения токенов:
- Вариант 1: Сохраните токен доступа в
localStorage
(и обновите токен вlocalStorage
илиhttpOnly
cookie): токен доступа может быть украден в результате XSS-атаки. - Вариант 2: Сохраните токен доступа и обновите токен в
httpOnly
cookie: подвержены CSRF, но могут быть смягчены, немного лучше с точки зрения воздействия XSS. - Вариант 3: Сохранить токен обновления в
httpOnly
cookie: безопасно от CSRF, немного лучше с точки зрения воздействия XSS.
Мы рассмотрим, как работает Option 3 , поскольку это лучший из трех вариантов.
Сохраните свой токен доступа в памяти и сохраните токен обновления в файле cookie:
Сохранение вашего токена доступа в памяти означает, что вы просто помещаете его в переменную (например,const accessToken = XYZ
) вместо того, чтобы помещать ее вlocalStorage
иликуки
Почему это безопасно для CSRF?
Да, отправка формы на / refresh_token
будет работать, и будет возвращен новый токен доступа, но злоумышленник не может прочитать ответ, если он использует форму HTML.Чтобы злоумышленник не смог успешно выполнить запрос fetch
или AJAX
и прочитать ответ, необходимо правильно настроить политику CORS сервера авторизации для предотвращения запросов с неавторизованных веб-сайтов.
Итак, как эта настройка работает?
Шаг 1: Вернуть токен доступа и обновить токен при аутентификации пользователя.
После аутентификации пользователя сервер авторизации вернет access_token
и refresh_token
. access_token
будет включен в тело ответа, а refresh_token
будет включен в cookie.
Refresh Token cookie setup:
- Используйте флаг
httpOnly
, чтобы JavaScript не читал его. - Используйте флаг
secure = true
, чтобы его можно было отправлять только по HTTPS. - По возможности используйте флаг
SameSite = strict
для предотвращения CSRF. Это можно использовать только в том случае, если сервер авторизации имеет тот же сайт, что и ваш интерфейс.Если это не так, ваш сервер авторизации должен установить заголовки CORS в бэкэнде или использовать другие методы, чтобы гарантировать, что запрос токена обновления может быть выполнен только авторизованными веб-сайтами.
Шаг 2: Сохранение токена доступа в памяти
Сохранение токена в памяти означает, что вы помещаете этот токен доступа в переменную на своем внешнем сайте (например, const accessToken = xyz
). Да, это означает, что токен доступа исчезнет, если пользователь переключит вкладки или обновит сайт.Вот почему у нас есть токен обновления. Мы не помещаем этот токен доступа в localStorage
или cookie
через JavaScript, потому что злоумышленникам легче сбрасывать эти данные, что делает их более уязвимыми для кражи с помощью XSS-атаки.
Шаг 3: Продлить токен доступа с помощью токена обновления
Когда токен доступа исчез или истек, нажмите на конечную точку / refresh_token
, и будет включен токен обновления, который был сохранен в файле cookie на шаге 1 в запросе.Теперь вы получите новый токен доступа и сможете использовать его для своих запросов API. Это означает, что ваш токен JWT может быть больше 4 КБ, и вы также можете поместить его в заголовок авторизации.
Вот и все!
Это должно охватывать основы и помочь вам защитить ваш сайт.
Ресурсы
При написании этого блога мы ссылались на несколько статей, особенно из этих статей:
Вопросы и отзывы
Если вам нужна помощь или хотите оставить отзыв, пожалуйста, оставьте комментарий здесь!
Где хранить токены обновления в браузере — ORY Hydra
На это есть два ответа:
a) Используйте OpenID Connect с автоматическим обновлением, которое не использует фактические токены обновления, а скрытый iframe, который использует файл cookie сеанса.
b) Используйте поток кода аутентификации с PKCE, учитывая следующие соображения:
Okta не имеет смысла, потому что новый токен обновления также будет храниться в том же браузере, поэтому вы по-прежнему уязвимы для XSS-атак.
У вас есть три варианта:
- Хранить в localStorage или подобном (leveldb,…)
- Хранить в js-читаемом файле cookie
- Хранить в httpOnly и безопасном cookie
В основном это сводится к двум подходам:
- Хранить токены с помощью JavaScript в браузере
- Хранить токены на сервере
В вашей модели угроз вы должны учитывать вероятность того, что вы подвергнетесь атаке XSS.Я бы использовал такие вопросы, как:
- Какие данные могли быть украдены? Достаточно ли он ценен для попытки XSS-атаки?
- Насколько велика вероятность XSS-атаки? Могу ли я отображать / анализировать / обрабатывать любой тип пользовательского ввода?
Если вероятность атаки XSS маловероятна и / или масштаб такой атаки будет очень ограниченным, вы можете рассмотреть возможность сохранения ее с помощью JavaScript в браузере (localStorage,…). Однако имейте в виду, что:
- Один XSS может быть использован для кражи всех данных в этих объектах, поэтому снова рекомендуется не хранить конфиденциальную информацию в локальном хранилище.
- , один XSS может использоваться для загрузки вредоносных данных и в эти объекты, поэтому не считайте объекты в них надежными.
Также неплохо иметь очень, очень строгую политику происхождения , если вы решите пойти по этому пути.
Итак, как видите, ограниченный токен обновления не решит вышеуказанные проблемы. Это действительно больше похоже на действительно плохое псевдорешение.
Если вы решите, что хранить его в браузере слишком опасно, конкретная реализация зависит от вашего приложения.У Auth0 есть несколько хороших отзывов по этому поводу. Вы можете найти их здесь:
Auth0 ДокументыГде хранить токены
В этом руководстве мы описываем, как хранить токены, используемые при аутентификации на основе токенов.
Рекомендации по безопасности для управления токенами доступа к API
Эта статья включена в новое руководство DZone по динамической веб- и мобильной разработке. Получите бесплатную копию, чтобы получить больше проницательных статей, отраслевой статистики и многого другого!
Современные приложения, как веб-приложения, так и собственные, для доступа к защищенным ресурсам используют API-интерфейсы на сервере.Чтобы авторизовать доступ к этим API, запрос должен включать какой-либо токен или ключ доступа. Эта статья посвящена передовым методам обеспечения безопасности для управления токенами доступа — как для поставщиков API, так и для разработчиков приложений.
Давайте сначала поговорим о доверии!
Когда речь идет о безопасности, преобладает одно правило: никому не доверять. Если вы являетесь поставщиком API, вы не можете быть уверены в том, что приложение, вызывающее API, является тем, которое вы ожидаете, что полученный вами токен не был украден или что связь между клиентом и сервером не была перехвачена.На стороне клиента вы не можете быть уверены, что приложение не будет декомпилировано (раскрывая встроенные секреты), что хранилище приложения не будет скомпрометировано посредством XSS-атаки или что ваших пользователей не обманывают, заставляя отправлять поддельные запросы.
Это означает, что вы должны принять надлежащие меры для безопасного получения, хранения и управления токенами безопасности, необходимыми для вызова серверных API.
Кроме того, вы можете подумать, что ваши API безопасны, если никогда не рекламировали их публично.Для вас они кажутся личными, потому что используются только вашими корпоративными приложениями. Однако, если их можно использовать из мобильного приложения, они находятся в общедоступном Интернете и, следовательно, общедоступны. Любой API, доступный за пределами вашей корпоративной сети, должен считаться общедоступным.
Получение токенов и ключей API
Когда дело доходит до использования API, вам обычно предлагается два варианта: передать статический фрагмент информации вместе с вызовом API или получить этот фрагмент информации динамически до вызова API.Эта информация обычно представляет собой токен доступа или ключ API. BasicAuth по-прежнему используется для некоторых API-интерфейсов по устаревшим причинам, но не рекомендуется в качестве основного решения.
При разработке аспектов безопасности вашего API вы должны с умом выбрать, как ваши потребители API будут обращаться к нему. Как обычно с мерами безопасности, индуцированный риск является ключевым фактором, который необходимо учитывать. Защита API, который позволяет только просматривать данные о погоде, сильно отличается от защиты API банковских платежей.
Хотя использование ключа API проще для разработчика, он не обеспечивает такой же уровень безопасности, как токен доступа, полученный с помощью двухфакторной аутентификации пользователя и надлежащей идентификации клиентского приложения.Более того, ключ API не несет никакой информации о пользователе и не может использоваться на бэкэнд-уровне, чтобы решить, какие операции разрешено вызывать потребителю API. Наконец, ключи API никогда не истекают, если они не отозваны поставщиком API.
OAuth был создан для устранения этих недостатков:
Приложение, обращающееся к ресурсу, известно (с использованием учетных данных клиентского приложения).
Поставщик API может определять области для ограничения доступа к определенным операциям (вы можете ПОЛУЧИТЬ запись каталога, но не можете ПОЛУЧИТЬ новую запись каталога, даже с действующим токеном).
Токены имеют ограниченный срок жизни.
Начнем с терминологии
Терминология OAuth иногда может сбивать с толку. В таблице ниже мы представляем отображение практической терминологии, ориентированной на разработку, на терминологию OAuth.
Практическое название | Терминология OAuth | Описание |
Приложение | Клиент | Клиент — это приложение, обращающееся к ресурсу от имени пользователя. |
Приложения веб-сервера | Конфиденциальный клиент | Приложение, работающее на стороне сервера и способное безопасно хранить секрет приложения. |
Одностраничные приложения / браузерные приложения / мобильные приложения | Государственный клиент | Приложение, полностью работающее на стороне клиента или на устройстве, которое не может безопасно хранить секрет приложения. |
API | Сервер ресурсов | API — это средство доступа к ресурсам, принадлежащим пользователю (например,грамм. банковский счет). |
Сервер OAuth | Сервер авторизации | Сервер OAuth отвечает за обработку запросов на управление токенами OAuth (авторизация доступа, выдача токенов, отзыв токенов). |
Пользователь | Владелец ресурса | Человек, предоставляющий доступ к ресурсу, к которому приложение пытается получить доступ. |
Маркер доступа | Жетон на предъявителя | Маркер доступа разрешает приложению доступ к API. |
Непрозрачный по сравнению с JWT
OAuth не требует обязательного формата токена доступа, и поэтому, в зависимости от реализации сервера OAuth, токен доступа может быть непрозрачным (обычно это длинная строка, не содержащая информации) или веб-токеном JSON (JWT).
Ключевым преимуществом JWT является возможность содержать утверждения или информацию о пользователе, которую серверные службы могут использовать для принятия решений бизнес-логики.
Изучение танца OAuth
Типы предоставления OAuth определяют, как клиент может получить токен.Наша команда обычно называет это «танцем OAuth». В мире OAuth есть много способов танцевать, но вы должны изучить только один: код авторизации. В некоторых случаях могут быть полезны другие типы предоставления, но тип предоставления кода авторизации является рекомендуемым способом получения токена доступа для всех типов приложений: веб-приложений, собственных приложений и мобильных приложений.
Для публичных клиентов и мобильных приложений, в частности, рекомендуется дополнительная мера безопасности, чтобы предотвратить кражу кода авторизации.Этот уровень безопасности описан в стандарте Proof Key for Code Exchange (PKCE, произносится как «пикси»). Вы можете узнать больше о PKCE и о том, как его использовать здесь. Если вы являетесь поставщиком API, убедитесь, что ваш сервер OAuth поддерживает эту опцию.
Вы должны проявлять особую осторожность с предоставлением пароля владельца ресурса: будучи самым простым в реализации, он довольно привлекателен. Однако, поскольку его основным требованием является доверие клиент-сервер, вам, вероятно, никогда не следует его использовать.
Рекомендации по управлению токенами
Остерегайтесь утечек учетных данных приложения OAuth
Храните код вашего приложения в GitHub? Хранятся ли там ваши учетные данные приложения OAuth и, в частности, секрет клиента? Это источник номер один утечек учетных данных на сегодняшний день.Если эти учетные данные украдены, любой может притвориться вами. Если вы считаете, что учетные данные могли быть скомпрометированы, немедленно восстановите их.
Кроме того, никогда не помещайте секрет клиента в распределенный код, например приложения, загруженные через магазин приложений или клиентский JavaScript.
Не жестко кодируйте токены в приложениях
Может возникнуть соблазн упростить код, чтобы получить токен на длительный период времени и сохранить его в своем приложении. Не надо. Делать. Что.
Обращайтесь с токенами так же, как с паролями
Жетоны — это ключ от двери! Токены и ключи API позволяют любому, у кого они есть, получить доступ к ресурсу.По сути, они так же важны, как и пароли. Относитесь к ним так же!
OAuth не является протоколом аутентификации
OAuth — это делегирование доступа к ресурсу. Это не протокол аутентификации (несмотря на название). Думайте о жетонах как о гостиничных картах. Вам необходимо пройти аутентификацию, чтобы получить ключ от отеля, но если он у вас есть, это никоим образом не подтверждает вашу личность. Провайдеры API не должны полагаться на владение токенами как на подтверждение личности, что подтверждается недавней утечкой пользовательской информации.
Вам действительно стоит взглянуть на OpenID Connect (OIDC), дополнительную спецификацию, вместо того, чтобы пытаться самостоятельно реализовать аутентификацию поверх OAuth. OIDC позволяет пользователю делиться некоторыми аспектами своего профиля с приложением без необходимости делиться своими учетными данными.
Остерегайтесь того, что вы храните в JWT, и кто имеет к ним доступ
JWT могут хранить большое количество информации в форме утверждений и могут быть легко проанализированы в случае захвата (если они не зашифрованы).Если вы используете JWT для передачи информации, которая полезна только для серверных служб, вы можете использовать другой подход: JWT могут хранить много информации в форме утверждений и могут быть легко проанализированы в случае захвата (если они не зашифрованы). Если вы используете JWT для передачи информации, которая полезна только для серверных служб, вы можете использовать другой подход:
Используйте непрозрачную строку или базовый JWT между клиентом и серверной частью.
На бэкэнде подтвердите запрос и внедрите новый JWT с полезной нагрузкой, содержащей утверждения, которые используются в нисходящем направлении.Эта функция предоставляется многими шлюзами безопасности API из коробки.
Если вы хотите использовать один и тот же токен во всем потоке, и он потенциально может нести конфиденциальную информацию, зашифруйте полезную нагрузку токена. При этом никогда не используйте JWT для передачи учетных данных пользователя, таких как пароли!
Тщательная проверка JWT
Когда вы получаете JWT на стороне сервера, вы должны тщательно проверить его содержимое. В частности, вам следует отклонить любой JWT, который не соответствует ожидаемому алгоритму подписи или использует слабые алгоритмы или слабые асимметричные / симметричные ключи для подписи.Кроме того, вы должны проверить все заявки, дату истечения срока действия, эмитентов и аудиторию.
Некоторые библиотеки и инструменты делают это за вас; другие необходимо сначала правильно настроить; некоторые делают только частичные проверки. Примите соответствующие меры в зависимости от используемых вами библиотек.
Не хранить токены в локальном хранилище; Используйте безопасные файлы cookie
Локальное хранилище браузера и хранилище сеансов могут быть прочитаны из JavaScript, и поэтому небезопасно хранить конфиденциальную информацию, такую как токены.Вместо этого используйте безопасные файлы cookie, флаг httpOnly
и меры CSRF для предотвращения кражи токенов.
Всегда транспортировать токены через HTTPS и в теле запроса
Тем самым вы ограничиваете риск того, что токен будет захвачен на лету или будет записан в журналы прокси или серверные журналы. Вы также должны убедиться, что используете только TLS 1.2 / 1.3 и наиболее безопасные комплекты шифров для всех участников, участвующих в выпуске и проверке токенов.
Использование специального представления браузера для запроса информации о согласии
Многие приложения используют встроенный пользовательский агент, но этого следует избегать, поскольку он не позволяет пользователю правильно проверить, с каким сайтом он обращается.Более того, приложение будет иметь полную видимость учетных данных, которые вводит пользователь. Некоторые поставщики API принимают решительные меры против этой практики, что поощряется стандартом лучших практик для нативных приложений OAuth.
Заключение
Маркеры доступа имеют основополагающее значение для реализации современных приложений, но с ними необходимо обращаться осторожно. Как внутренний разработчик, вы должны убедиться, что предоставили правильный тип предоставления для получения токенов доступа, поддержки PKCE для мобильных приложений и тщательной проверки JWT.