JSON Web Token (JWT) — это открытый стандарт (RFC 7519) для создания токенов доступа, основанный на формате JSON. Как правило, используется для передачи данных для аутентификации в клиент-серверных приложениях. Токены создаются сервером, подписываются секретным ключом и передаются клиенту, который в дальнейшем использует данный токен для подтверждения своей личности.
53 307 просмотров
В простом понимании — это строка в специальном формате, которая содержит данные, например, ID и имя зарегистрированного пользователя. Она передается при каждом запросе на сервер, когда необходимо идентифицировать и понять, кто прислал этот запрос.
В этой статье разберу, что такое Access токен, Refresh токен и как с ними работать.
Для дальнейших разборов будет использован токен:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1ODEzNTcwMzl9.E4FNMef6tkjIsf7paNrWZnB88c3WyIfjONzAeEd4wF0
После того, как посетитель прошел авторизацию в нашей системе, указав свой логин и пароль, система выдает ему 2 токена: access token и refresh токен.
OAuth2 и KeyCloak: что такое Access Token (2022)
После чего посетитель, когда хочет получить с сервера данные, например, свой профиль, вместе с запросом он передает Access токен, как на примере выше. Сервер, получив его проверяет, что он действительный (об этом чуть ниже), вычитывает полезные данные из него (тот же user_id) и, таким образом, может идентифицировать пользователя.
Токен разделен на три основные группы: заголовок, полезные данные и сигнатура, разделенные между собой точкой.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 — это первая часть токена — есть заголовок. Она закодирована в Base64 и если её раскодировать, получим строку:
Это можно проверить прям в браузере, выполнив в консоле или js коде:
const header = atob(‘eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9’); console.log(header);
typ — это наш тип токена JWT. Alg — алгоритм шифрования HMAC-SHA256. Их может быть несколько, но здесь буду говорить именно об этом алгоритме.
PAYLOAD или полезные данные
Вторым блоком идет eyJ1c2VyX2lkIjoxLCJleHAiOjE1ODEzNTcwMzl9
Это есть полезные данные, так же закодированные в Base64. После раскодирования получим:
Данные могут быть любыми. Главное, чтобы по ним можно было идентифицировать пользователя. В нашем случае — это user_id и exp — время окончания действия текущего токена.
Поскольку необходимо ограничивать токен по времени, поле exp обязательно. По нему можно проверить, актуален ли токен или нет.
Последняя часть токена — наиболее важная. У нас это E4FNMef6tkjIsf7paNrWZnB88c3WyIfjONzAeEd4wF0
Как вы уже могли заметить — первые данные передаются практически в открытом виде и раскодировать их может любой. Но шифровать их нет необходимости. Цель токена — подтвердить, что эти данные не были изменены. Вот для этих целей и выступает сигнатура. И чтобы её сгенерировать нужен приватный ключ.
Ну или некая секретная фраза, которая находится только на сервере. Только с помощью этого ключа мы можем создать сигнатуру и проверить, что она была создана именно с помощью его.
КАК УЗНАТЬ СВОЙ Access_Token ВКОНТАКТЕ
Она получается примерно следующим образом:
Берем заголовок, например и кодируем его в base64, получаем ту самую часть eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Тоже самое проделываем с данными eyJ1c2VyX2lkIjoxLCJleHAiOjE1ODEzNTcwMzl9
После этого склеиваем их и получаем eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1ODEzNTcwMzl9
Далее эти данные шифруем с помощью нашего алгоритма HMAC-SHA256 и ключа.
const header = ‘<«alg»:»HS256″,»typ»:»JWT»>’ // строка const payload = » // строка // кодируем заголовок и данные в base64 const headerBase64 = base64urlEncode(header) const payloadBase64 = base64urlEncode(payload) // склеиваем точкой полученные строки const data = headerBase64 + ‘.’ + payloadBase64 // кодируем алгоритмом шифрования нашим ключем шифрования const secret = ‘123456’ const sig = HMAC-SHA256(data, secret) // и, наконец, получаем окончательный токен const jwt = data + ‘.’ + sig
Проверка токена
Для проверка токена необходимо проделать ту же операцию.
Берем склейку заголовок + данные, кодируем с помощью алгоритма HMAC-SHA256 и нашего приватного ключа. А далее берем сигнатуру с токена и сверяем с результатом кодирования. Если результаты совпадают — значит данные подтверждены и можно быть уверенным, что они не были подменены.
Refresh token
Основной токен, про который шла речь выше, обычно имеет короткий срок жизни — 15-30 минут. Больше давать не стоит.
Как только время выйдет, пользователю снова придется проходить авторизацию. Так вот чтобы этого избежать, существует Refresh токен. С помощью него можно продлить Access токен.
В действительности, Refresh токен обязательно должен быть одноразовым. Его задача — получить новую пару токенов. Как только это было сделано, предыдущий токен будет считаться недействительным. Срок жизни Refresh токена уже может быть большим — до года, а может даже и больше.
У него, обычно, нет какой-то структуры и это может быть некая случайная строка.
Для проекта odo24.ru я использовал следующий подход.
Генерируется Access токен и после случайная строка, например T6cjEbghMZmybUd_fhE
С нашего нового Access токена eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1ODEzNTcwMzl9.E4FNMef6tkjIsf7paNrWZnB88c3WyIfjONzAeEd4wF0 беру последние шесть знаков, получаю Ed4wF0
Склеиваю и получаю рефреш токен T6cjEbghMZmybUd_fhEEd4wF0
Это сделано для привязки Access токена к Refresh. Для получения новых токенов необходимо передать эти два токена. Делается проверка на их связку и только после валидируется Access токен. Если и второй этап прошел успешно, тогда получаем с базы данных по текущему user_id рефреш токен и сверяем с тем, что к нам пришел. Если они совпадают, тогда генерируются новые токены и в базе данных обновляется Refresh токен на новый.
Где хранить токены?
В моем случае я разделил оба токена и храню в разных местах. Access токен нужен только для идентификации пользователя и на клиенте (JS) он не нужен, поэтому он передается в Cookie (http only).
Refresh токен хранится в LocalStorage и используется только когда Access токен перестал быть актуальным.
Зачем 2 токена?
Представим ситуацию, когда у нас каким-то образом украли Access токен. Да, это уже плохо и где-то у нас брешь в безопасности. Злоумышленник в этом случае сможет им воспользоваться не более чем на 15-30 минут. После чего токен «протухнет» и перестанет быть актуальным. Ведь нужен второй токен для продления.
Если украли Refresh токен, то без Access токена (который недоступен в JS) продлить ничего нельзя и он оказывается просто бесполезным.
Самая неприятная ситуация — это когда удалось увести сразу 2 токена. В этом случае злоумышленник сможет пользоваться системой неограниченное время. Точнее когда пользователь попытается войти в систему, его не пустит, т.к. его Refresh токен уже будет неактуальным, и ему придется вводить логин и пароль. Только в этом случае злоумышленник потеряет контроль над чужой учетной записью.
Постскриптум
В своей реализации Refresh токена использовал общую длину 24 знака. Первые 6 знаков — это дата его «протухания», следующие 12 знаков — случайно сгенерированные данные. И в конце 6 знаков — это часть Access токена последней части сигнатуры.
Дату протухания внедрил прям в токен с той целью, чтобы не хранить эту информацию где-то в другом месте, например, в базе данных.
Дата содержит год, месяц, день, час и минуты. Хранится в ASCII
Кодирование даты на Golang:
// приводим к целочисленному числу uint32. Итого 32 бита. // расчет простой: год 12 бит, месяц 4 бита, день 5 бит и т.д. Таким образом в аккурат умещаемся в 32 бита или 4 байта. date := uint32(year<<20) | uint32(month<<16) | uint32(day<<11) | uint32(hour<<6) | uint32(minute) // в цикле кодируем байты в ASCII. 1 знак это шесть бит. Итого и получаем шесть знаков даты по таблице ASCII — печатные знаки. for n := 0; n < 6; n++ < b6Bit = byte(date>>i)
Всю реализацию на Go можно изучить на Github-е
Заключение
В этой статье попытался рассказать о взаимодействии двух токенов и как ими пользоваться. В сети достаточно много информации о Access токенах, однако мало, как мне показалось, информации о Refresh токенах.
Источник: vc.ru
Как получить токен Вконтакте
При разработке приложений связанных с работой API Вконтакте возникает необходимость получить ключ доступа пользователя (access_token). Для этой цели я использую проверенный временем способ, а именно получение токена через ссылку авторизации в приложении Вконтакте на Android.
Зачем нужен токен Вконтакте
access_token – это специальный ключ доступа, который работает на базе протокола авторизации OAuth 2.0 и генерируется с помощью логина и пароля пользователя. В отдельных случаях токен генерируется прямо в интерфейсе социальной сети, например для получения доступа к приложению или сообществу.
С помощью токена (access_token) вы можете использовать практически весь функционал социальной сети Вконтакте. Узнать полный список методов для работы с API Вконтакте вы можете по ссылке: https://vk.com/dev/methods
Существует несколько типов токенов:
- Ключ доступа пользователя – для доступа к функционалу пользователя
- Ключ доступа сообщества – для доступа к функционалу сообщества
- Ключ доступа приложения – для доступа к функционалу приложения
Как получить ключ доступа пользователя
Мы рассмотрим два способа получения токена (access_token) пользователя:
- С помощью логина и пароля
- С помощью логина, пароля и дфухфакторной авторизацией
Получение ключа доступа пользователя с помощью логина и пароля:
- Открываем ссылку: https://api.vk.com/oauth/token?grant_type=passwordclient_secret=hHbZxrka2uZ6jB1inYsHpassword=МОЙ-ПАРОЛЬ (предварительно подставив свои данные в переменные username= и password=
- В окне вы увидите следующее сообщение:
- Вам необходимо перейти к адресной строке и скопировать ключ который находится после access_token= и до client_id=2274003username=НОМЕР-ТЕЛЕФОНАuser_id
Данный набор букв и цифр это и есть ваш ключ доступа пользователя (access_token).
Как получить ключ доступа сообщества
- Заходим в сообщество где вы являетесь администратором
- Переходим в раздел “Управление”
- Переходим в раздел “Работа с API”
- Нажимаем “Создать ключ” и выбираем необходимые права доступа:
- Нажимаем “Создать”
- От выбранного типа подтверждения действий вам придет СМС или push – уведомление
- Подтверждаем создание ключа:
- Ключ успешно создан
* Для работы с Callback API и Long Poll API используйте полученный ранее токен сообщества.
Как получить ключ доступа приложения
- Переходим в раздел управления приложениями: https://vk.com/apps?act=manage
- Нажимаем “Создать приложение”
- Заполняем данные:
- Переходим в “Настройки приложения” где видим сервисный ключ доступа
Мы рассмотрели самые популярные способы получения токена (access_token) для работы с API Вконтакте.
Если у вас возникнут трудности при получении токена для работы с API Вконтакте, пишите в комментариях или мне в телеграм.
Источник: yakovtsov.ru
Идентификационный токен и токен доступа: в чем разница?
«Давайте воспользуемся токеном для защиты вызова API. Что мне использовать: ID-токен или Access токен? ID токен мне кажется предпочтительнее. В конце концов, если я знаю, кто является пользователем, я могу принимать более обоснованные решения об авторизации, верно?» Вам когда-нибудь приходилось приводить подобные аргументы?
Выбор, основанный на интуиции, может оказаться хорошим, но то, что кажется интуитивным, не всегда верно. В случае ID и Access токенов, имеющих ясные и четко определенные цели, пользоваться ими нужно, исходя из этих соображений. Использование неправильного токена может привести к тому, что ваше решение будет небезопасным. «Что в конце концов изменится? Это всего лишь токены.
Я могу использовать их по своему усмотрению. Что такого плохого может случиться?» Давайте подробнее рассмотрим эти два типа токенов, чтобы лучше понять их роль в процессах аутентификации и авторизации.
Что такое идентификационный токен?
ID токен — это артефакт, подтверждающий, что пользователь прошел аутентификацию. Он был представлен OpenID Connect (OIDC), открытым стандартом аутентификации, используемым многими системами идентификации такими, как Google, Facebook и, конечно же, Auth0. Ознакомьтесь с этим документом для получения дополнительных сведений об OpenID Connect. Давайте кратко рассмотрим проблему, которую призван решить OIDC.
Рассмотрим следующую схему: Здесь пользователь со своим браузером аутентифицируется через провайдер OpenID и получает доступ к веб-приложению. Результатом процесса аутентификации на основе OpenID Connect является ID токен, который передается приложению в качестве доказательства того, что пользователь прошел аутентификацию.
Подтверждение аутентификации пользователя это всего лишь базовое представление об ID токене. Рассмотрим это подробнее. Идентификационный токен JSON Web Token (JWT) — стандартный формат, который позволяет вашему приложению легко проверить его содержимое и убедиться, что оно исходит от ожидаемого эмитента и что никто другой его не менял. Если вы хотите узнать больше о JWT, посмотрите «The JWT Handbook». Проще говоря, пример ID токена выглядит так: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbXktZG9tYWluLmF1dGgwLmNvbSIsInN1YiI6
ImF1dGgwfDEyMzQ1NiIsImF1ZCI6IjEyMzRhYmNkZWYiLCJleHAiOjEzMTEyODE5NzAsImlhdCI6MTMxMTI4MDk3MCwibm
FtZSI6IkphbmUgRG 9lIiwiZ2l2ZW5fbmFtZSI6IkphbmUiLCJmYW1pbHlfbmFtZSI6IkRvZSJ9 Конечно, просто «на глазок» это не прочесть, поэтому вам нужно расшифровать его, чтобы увидеть, какой контент содержит JWT. Между прочим, ID токен не зашифрован, а закодирован только в Base 64. Вы можете использовать одну из множества доступных библиотек для его декодирования или самостоятельно проверить его с помощью сайта jwt.io.
Не вдаваясь в подробности, соответствующая информация, содержащаяся в указанном выше ID токене, выглядит следующим образом: < «iss»: «http://my-domain.auth0.com», «sub»: «auth0|123456», «aud»: «1234abcdef», «exp»: 1311281970, «iat»: 1311280970, «name»: «Jane Doe», «given_name»: «Jane», «family_name»: «Doe» >Эти свойства JSON называются «claims (заявки)», и они представляют собой заявления о пользователе и самом токене. Заявки о пользователе позволяют определить его личность.
Фактически, спецификации OpenID Connect не требуют, чтобы ID токен содержал заявку о пользователе. В своей минимальной структуре он содержит данные только для аутентификации. Одним из важных требований является «aud» заявка. Оно определяет получателя, то есть веб-приложение, которое должно быть конечным получателем токена.
В случае с использованием ID токена, значением «aud» будет Client ID приложения, которое должно использовать токен. Запомните это небольшое уточнение об ограничении целевой информационной системы, поскольку оно поможет вам лучше понять, как в дальнейшем им правильно пользоваться.
Идентификационный токен может содержать дополнительную информацию о пользователе: адрес его электронной почты, фотографию, день рождения и т. д. Наконец, возможно, самое важное: ID токен подписывает эмитент своим закрытым ключом. Для вас это гарантия происхождения токена и того, что он не был подделан. Это можно проверить, используя открытый ключ эмитента. Здорово!
Теперь вы знаете, что такое идентификационный токен. Но что вы можете с ним делать? Во-первых, он демонстрирует, что пользователь был аутентифицирован организацией, которой вы доверяете (провайдер OpenID), и поэтому вы можете доверять его личным данным.
Кроме того, ваше приложение может персонализировать взаимодействие с пользователями, используя данные о пользователе, включенные в ID токен. Например, вы можете показать имя в пользовательском интерфейсе или отобразить сообщение «С наилучшими пожеланиями» в день рождения. Самое интересное в том, что вам не нужно делать дополнительных запросов, поэтому вы можете немного повысить производительность своего приложения.
Что такое токен доступа?
Теперь, когда вы знаете, что такое идентификационный токен, давайте попробуем понять, что такое Access токен. Начнем с описания сценария, в который вписывается токен доступа: На схеме выше клиентское приложение хочет получить доступ к ресурсу, например API или чему-либо еще, что защищено от несанкционированного доступа.
Два других элемента на этой диаграмме — это пользователь, который является владельцем ресурса, и сервер авторизации. В этом сценарии Access токен является артефактом, позволяющим клиентскому приложению получить доступ к ресурсу пользователя. Он выдается сервером авторизации после успешной аутентификации пользователя и получения его согласия.
В контексте OAuth 2 Access токен позволяет клиентскому приложению получать доступ к определенному ресурсу для выполнения определенных действий от имени пользователя. Что известно как сценарий делегированной авторизации: пользователь делегирует клиентскому приложению доступ к ресурсу от своего имени.
Это значит, например, что вы можете от своего имени разрешить приложению LinkedIn доступ к API Twitter для перекрестной публикации на обеих социальных платформах. Заметьте, что вы разрешаете LinkedIn только публиковать свои сообщения в Twitter. Вы не разрешаете ему удалять их, изменять данные вашего профиля или делать что-то еще.
Это ограничение очень важно в сценарии делегированной авторизации и достигается с помощью областей действия, или scopes. Области действия — это механизм, позволяющий пользователю авторизовать стороннее приложение для выполнения только определенных операций.
Конечно, API, получающий Access токен, должен получить подтверждение, что это в самом деле действительный токен, выпущенный сервером авторизации, которому он доверяет, и принимать решения об авторизации на основе связанной с ним информации. Другими словами, API должен каким-то образом использовать этот токен, чтобы авторизовать клиентское приложение для выполнения желаемой операции с ресурсом.
Как следует использовать Access токен для принятия решений об авторизации, зависит от многих факторов: общей архитектуры системы, формата токена и т. д. Например, токен доступа может быть ключом, который позволяет API извлекать необходимую информацию из базы данных, совместно используемую с сервером авторизации, или может напрямую содержать необходимую информацию в закодированном формате. Это значит, что понимание того, как получить необходимую информацию для принятия решений об авторизации, является соглашением между сервером авторизации и сервером ресурсов, то есть API.
В спецификации OAuth 2 ничего не говорится о формате Access токена. Это может быть строка в любом формате. Распространенным форматом, используемым для токенов доступа, является JWT, и на данный момент этот стандарт в разработке. Однако это не значит, что Access токены должны быть именно в этом формате. Хорошо!
Теперь вы знаете, что такое ID-токен и Access токен. Итак, вы готовы использовать их, не боясь ошибиться. Но подождите. Мне кажется, вы не уверены. Возможно, вам нужна другая информация.
Ok. Итак, давайте посмотрим, для чего эти токены не подходят.
Для чего НЕ подходит ID-токен?
Одна из наиболее распространенных ошибок, допускаемых разработчиками при использовании идентификационного токена — это использование его для вызова API. Как сказано выше, ID токен доказывает, что пользователь прошел аутентификацию.
В собственном сценарии, то есть в сценарии, в котором клиент и API контролируются вами, вы можете решить, что ваш идентификационный токен подходит для принятия решений об авторизации и, возможно, все, что вам нужно знать — это личность пользователя. Однако даже в этом сценарии безопасность вашего приложения, состоящего из клиента и API, может быть под угрозой.
Фактически, не существует механизма, который привязывает ID токен к каналу клиентского API. Если злоумышленнику удастся украсть вашу «личность», он может использовать ее для вызова вашего API как законного клиента.
С другой стороны, для Acces токена существует набор методов, известных как ограничение отправителя (sender constraint), которые позволяют привязать токен доступа к определенному отправителю. Это гарантия того, что даже если злоумышленник украдет Access токен, он не сможет использовать его для доступа к вашему API, поскольку токен привязан к клиенту, который изначально его запросил.
В сценарии делегированной авторизации, когда сторонний клиент хочет вызвать ваш API, нельзя использовать ID токен для вызова API. Помимо отсутствия механизмов привязки к клиенту есть несколько других причин, по которым этого не следует делать.
Если ваш API принимает ID токен в качестве токена авторизации, вы сначала игнорируете предполагаемого получателя, указанного в aud (audience claim). В этом утверждении говорится, что он предназначен для вашего клиентского приложения, а не для сервера ресурсов (т. е. API). Можно подумать, что это всего лишь формальность, но такой подход может повлечь за собой риски для безопасности.
Прежде всего, кроме прочих проверок, ваш API не должен принимать токен, который для него не предназначен. Если это произойдет, его безопасность окажется под угрозой. Фактически, если вашему API все равно, предназначен ли для него токен, для доступа к нему может быть использован ID токен, украденный из любого клиентского приложения, может быть использован для доступа к вашему API.
Разумеется, для предотвращения несанкционированного доступа, проверка aud — это всего лишь одна из проверок, которую должен выполнять ваш API. Кроме того, вашему идентификатору не будут предоставлены области действия (да, это еще одна боль). Как было сказано ранее, области позволяют пользователю ограничивать операции, которые ваше клиентское приложение может выполнять от их имени. Эти области связаны с Access токеном, чтобы ваш API знал, что может делать клиентское приложение, а что нет. Если ваше клиентское приложение использует ID токен для вызова API, вы игнорируете эту функцию и потенциально разрешаете приложению выполнять действия, не авторизованные пользователем.
Для чего НЕ подходит Access токен?
Что касается Access токена, то он был задуман, чтобы продемонстрировать, что вы авторизованы для доступа к ресурсу, например, для вызова API. Ваше клиентское приложение должно использовать его только с этой целью. Другими словами, Access токен не должен проверяться клиентским приложением.
Он предназначен для сервера ресурсов, и клиентское приложение должно обрабатывать Access токены как непрозрачные строки, то есть строки без определенного значения. Даже если вам известен формат Access токена, не следует пытаться интерпретировать его содержимое в клиентском приложении. Как уже говорилось, формат Access токена — это соглашение между сервером авторизации и сервером ресурсов, и клиентское приложение не должно вмешиваться. Подумайте, что может случиться, если однажды формат Access токена изменится. Если ваш клиентский код (client code) проверял этот Access токен, в этом случае он будет тотчас сломан.
Краткий обзор
Путаница с использованием ID и Access токенов очень распространена, и, возможно, трудно понять различия между ними. Может быть, это в основном связано с отсутствием четкого понимания различных целей каждого артефакта, определенных в спецификациях OAuth и OpenID Connect. Кроме того, понимание сценариев, в которых изначально должны были действовать эти артефакты, играет важную роль в предотвращении путаницы при их использовании. Тем не менее, я надеюсь, что теперь эта тема немного прояснилась. В иллюстрации кратко изложено то, что можно и чего нельзя делать с ID и Access токенами:
Переведено со статьи, полный текст доступен по ссылке.
Источник: cryptoarm.ru