Understanding the concept of JWT — JSON Web Tokens
JWT or JSON Web Token is an open standard (RFC 7519) which is used to securely transfer information between two parties.
To understand the detail concept of JWT, it’s very important to first know about Session tokens.
Session Tokens are an encrypted unique strings that are used to identify Session Instances. Look at the understandable example below-
Think of a Customer Care Dept. in a city, if a person(A) enters into it who has any queries to speak with representatives. Initially a person would speaks about all his problems and queries, then normally the care dept. would note down all the queries that particular customer has on a single piece of paper or in a database, and the point here is that, they would provide the customer with a Customer ID no. or Case ID no. which contains all information about queries or problems, as this would make customer care dept. to search for particular case in much faster way next time the same customer arrives for the solution.
Now Let’s think the same procedure with Clients and Servers —
Think of any website that contains Registration forms, here once the user enters into particular website and registers with his/her data. This data directly hits the server and on the server sends a token for that particular browser. The token is stored in the cookie of the browser and can be valid until the user logs off or until any time period. This token validates and helps the user to access all the subsequent requests made by him/her.
This method of validating and authorizing the user was much proper, but there was a key drawback to use session tokens. Let’s look at a example of Online Banking Systems, let’s imagine a scenario here, if a person logs in with his/her credentials on any banking website, Server(A) would pass a session token to the browser and hence here only Server(A) would authorize the current user as it has valid session token to match with its corresponding. And if any subsequent request would pass to Server(B), there would be conflict as Server(B) doesn’t know about historical tokens. This drawback gave birth to JWT.
JSON Web Tokens —
Let’s dive directly into the same example —
If a person, has problems to ask for a customer representative, the customer would visit the Care dept. and similarly rept. would note down all the problems with a Signature or Customer ID, so that if next time a customer enters the dept., a representative must identify the problems once they verify the Signature or Customer ID. But in this case, the document would be handover to customer, where the customer must bring the document whenever they enters dept. This saves the complexity that a rept. would be facing at the time of searching for particular customer Case ID and lot more other beneficial things.
Now Let’s think the same procedure with Clients and Servers —
In this case, Once a user registers or logs in with his or her credentials, a server generates a JWT token and assigns it with the data, and passes it to client-side. This token can only be verified by server, which on the client side it is stored in cookies of browsers and helps the browser or client to access all subsequent requests in no time. This brings lot of Reliability to users and helps in the process of Authentication.
Structure of JWT-
There must be 3 parts in which JWT structure is Divided —
- Headers
Usually, headers are first part in JWT’s which consist of Algorithm used to encode JWT and type of the token which is JWT by-default.
Payload section is the middle part of JSON web tokens, which consists of User Data, which is passed between Client and Server.
Signature is the third part of the JWT which is created by server, and used to validate the requests, done by the user. To create the signature, the base-64 encoded header and payload are taken, along with a secret key and signed with algorithm specified in the header.
This Entire JWT is embedded in a type of string and these 3 parts are separated by dots(.).
JWT — как безопасный способ аутентификации и передачи данных
JSON Web Token (JWT) — это открытый стандарт (RFC 7519) для создания токенов доступа, основанный на формате JSON. Как правило, используется для передачи данных для аутентификации в клиент-серверных приложениях. Токены создаются сервером, подписываются секретным ключом и передаются клиенту, который в дальнейшем использует данный токен для подтверждения своей личности.
В простом понимании — это строка в специальном формате, которая содержит данные, например, ID и имя зарегистрированного пользователя. Она передается при каждом запросе на сервер, когда необходимо идентифицировать и понять, кто прислал этот запрос.
В этой статье разберу, что такое Access токен, Refresh токен и как с ними работать.
Для дальнейших разборов будет использован токен:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1ODEzNTcwMzl9.E4FNMef6tkjIsf7paNrWZnB88c3WyIfjONzAeEd4wF0
После того, как посетитель прошел авторизацию в нашей системе, указав свой логин и пароль, система выдает ему 2 токена: access token и refresh токен.
После чего посетитель, когда хочет получить с сервера данные, например, свой профиль, вместе с запросом он передает Access токен, как на примере выше. Сервер, получив его проверяет, что он действительный (об этом чуть ниже), вычитывает полезные данные из него (тот же user_id) и, таким образом, может идентифицировать пользователя.
Токен разделен на три основные группы: заголовок, полезные данные и сигнатура, разделенные между собой точкой.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 — это первая часть токена — есть заголовок. Она закодирована в Base64 и если её раскодировать, получим строку:
Это можно проверить прям в браузере, выполнив в консоле или js коде:
typ — это наш тип токена JWT. Alg — алгоритм шифрования HMAC-SHA256. Их может быть несколько, но здесь буду говорить именно об этом алгоритме.
Вторым блоком идет eyJ1c2VyX2lkIjoxLCJleHAiOjE1ODEzNTcwMzl9
Это есть полезные данные, так же закодированные в Base64. После раскодирования получим:
Данные могут быть любыми. Главное, чтобы по ним можно было идентифицировать пользователя. В нашем случае — это user_id и exp — время окончания действия текущего токена.
Поскольку необходимо ограничивать токен по времени, поле exp обязательно. По нему можно проверить, актуален ли токен или нет.
Последняя часть токена — наиболее важная. У нас это E4FNMef6tkjIsf7paNrWZnB88c3WyIfjONzAeEd4wF0
Как вы уже могли заметить — первые данные передаются практически в открытом виде и раскодировать их может любой. Но шифровать их нет необходимости. Цель токена — подтвердить, что эти данные не были изменены. Вот для этих целей и выступает сигнатура. И чтобы её сгенерировать нужен приватный ключ. Ну или некая секретная фраза, которая находится только на сервере. Только с помощью этого ключа мы можем создать сигнатуру и проверить, что она была создана именно с помощью его.
Она получается примерно следующим образом:
Берем заголовок, например <"alg":"HS256","typ":"JWT">и кодируем его в base64, получаем ту самую часть eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Тоже самое проделываем с данными eyJ1c2VyX2lkIjoxLCJleHAiOjE1ODEzNTcwMzl9
После этого склеиваем их и получаем eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1ODEzNTcwMzl9
Далее эти данные шифруем с помощью нашего алгоритма HMAC-SHA256 и ключа.
Для проверка токена необходимо проделать ту же операцию.
Берем склейку заголовок + данные, кодируем с помощью алгоритма HMAC-SHA256 и нашего приватного ключа. А далее берем сигнатуру с токена и сверяем с результатом кодирования. Если результаты совпадают — значит данные подтверждены и можно быть уверенным, что они не были подменены.
Основной токен, про который шла речь выше, обычно имеет короткий срок жизни — 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 токен перестал быть актуальным.
Представим ситуацию, когда у нас каким-то образом украли Access токен. Да, это уже плохо и где-то у нас брешь в безопасности. Злоумышленник в этом случае сможет им воспользоваться не более чем на 15-30 минут. После чего токен «протухнет» и перестанет быть актуальным. Ведь нужен второй токен для продления.
Если украли Refresh токен, то без Access токена (который недоступен в JS) продлить ничего нельзя и он оказывается просто бесполезным.
Самая неприятная ситуация — это когда удалось увести сразу 2 токена. В этом случае злоумышленник сможет пользоваться системой неограниченное время. Точнее когда пользователь попытается войти в систему, его не пустит, т.к. его Refresh токен уже будет неактуальным, и ему придется вводить логин и пароль. Только в этом случае злоумышленник потеряет контроль над чужой учетной записью.
В своей реализации Refresh токена использовал общую длину 24 знака. Первые 6 знаков — это дата его «протухания», следующие 12 знаков — случайно сгенерированные данные. И в конце 6 знаков — это часть Access токена последней части сигнатуры.
Дату протухания внедрил прям в токен с той целью, чтобы не хранить эту информацию где-то в другом месте, например, в базе данных.
Дата содержит год, месяц, день, час и минуты. Хранится в ASCII
Кодирование даты на Golang:
Всю реализацию на Go можно изучить на Github-е
В этой статье попытался рассказать о взаимодействии двух токенов и как ими пользоваться. В сети достаточно много информации о Access токенах, однако мало, как мне показалось, информации о Refresh токенах.
Токен авторизации на примере JSON WEB Token
https://proglib.io/p/jwt-for-dummies/
Доброго времени суток, дорогой читатель. В данной статье я постараюсь рассказать об одном из самых популярных (на сегодняшний день) способов авторизации в различных клиент-серверных приложениях — токен авторизации. А рассматривать мы его будем на примере самой популярной реализации — JSON Web Token или JWT.
Введение
Начнем с того, что важно уметь различать следующие два понятия: аутентификации и авторизации. Именно с помощью этих терминов почти все клиент-серверные приложения основывают разделение прав доступа в своих сервисах.
Очень часто к процессу аутентификации примешивают и процесс индентификации — процесс, позволяющий определить что за пользователь в данный момент хочет пользоваться нашим приложением, например, путем ввода логина. Далее нам, как разработчикам и как ответственным людям хочется убедиться, что данный пользователь действительно тот за кого он себя выдает — и поэтому следует процесс аутентификации, когда пользователь подтверждает, что он тот самый %user_name%, например, путем ввода пароля.
Казалось бы, все что необходимо выполнить для безопасности нашего приложения мы сделали. Но нет, еще одним очень важным шагом в любом клиент-серверном приложении является разграничение прав, разрешение или запрет тех или иных действий данному конкретному аутентифицированному пользователю — процесс авторизации.
Еще раз кратко закрепим: сначала идет идентификация и аутентификация, процессы когда мы определяем и удостоверяемся, что за пользователь в данный момент использует наше приложение, а далее идет авторизация — процесс принятия решения о разрешенных данному пользователю действиях.
Еще одно небольшое введение
Прежде чем начать говорить о самом токене авторизации следует упомянуть для каких целей вообще его решили использовать. Поскольку мы знаем, что почти весь интернет так или иначе построен на протоколе HTTP(или его старшем брате HTTPS) и что он не отслеживает состояние, то есть при каждом запросе HTTP ничего не знает, что происходило до этого, он лишь передает запросы, то возникает следующая проблема: если аутентификация нашего пользователя происходит с помощью логина и пароля, то при любом следующем запросе наше приложение не будет знать все тот же ли этот человек, и поэтому придётся каждый раз заново логиниться. Решением данной проблемы является как раз наш токен, а конкретно его самая популярная реализация — JSON Web Tokens (JWT). Также помимо решения вопросов с аутентификацией токен решает и другую не менее важную проблему авторизации (разграничение разрешенных данному пользователю действий), о том каким образом мы узнаем ниже, когда начнем разбирать структуру токена.
Формальное определение
Приступим наконец к работе самого токена. Как я сказал ранее в качестве токенов наиболее часто рассматривают JSON Web Tokens (JWT) и хотя реализации бывают разные, но токены JWT превратились в некий стандарт, именно поэтому будем рассматривать именно на его примере.
JSON Web Token (JWT) — это открытый стандарт (RFC 7519) для создания токенов доступа, основанный на формате JSON.
Фактически это просто строка символов (закодированная и подписанная определенными алгоритмами) с некоторой структурой, содержащая полезные данные пользователя, например ID, имя, уровень доступа и так далее. И эта строчка передается клиентом приложению при каждом запросе, когда есть необходимость идентифицировать и понять кто прислал этот запрос.
Принцип работы
Рассмотрим принцип работы клиент серверных приложений, работающих с помощью JWT. Первым делом пользователь проходит аутентификацию, конечно же если не делал этого ранее и в этом есть необходимость, а именно, например, вводит свой логин и пароль. Далее приложение выдаст ему 2 токена: access token и refresh token (для чего нужен второй мы обсудим ниже, сейчас речь идет именно об access token). Пользователь тем или иным способом сохраняет его себе, например, в локальном хранилище или в хранилище сессий. Затем, когда пользователь делает запрос к API приложения он добавляет полученный ранее access token. И наконец наше приложение, получив данный запрос с токеном, проверяет что данный токен действительный (об этой проверке, опять же, ниже), вычитывает полезные данные, которые помогут идентифицировать пользователя и проверить, что он имеет право на запрашиваемые ресурсы. Таким нехитрым образом происходит основная логика работы с JSON Web Tokens.
https://habr.com/ru/post/336082/
Структура токена
Пришло время обсудить структуру токена и тем самым лучше разобраться в его работе. Первое что следует отметить, что JWT токен состоит из трех частей, разделенных через точку:
Полезные данные (playload)
funnytorimage.pw
Рассмотрим каждую часть по подробнее.
Заголовок
Это первая часть токена. Она служит прежде всего для хранения информации о токене, которая должна рассказать о том, как нам прочитать дальнейшие данные, передаваемые JWT. Заголовок представлен в виде JSON объекта, закодированного в Base64-URL Например:
Если раскодировать данную строку получим:
Заголовок содержит два главных поля: alg и typ. Поле typ служит для информации о типе токена, но как я уже упоминал ранее, что JWT превратился в некий стандарт, то это поле перестало нести особый смысл и служит скорее для целей будущего, если вдруг появится улучшенная версия алгоритма JWT(2.0), которая заменит JWT. Поле alg задает алгоритм шифрования. Обязательный для поддержки всеми реализациями является алгоритм HMAC с использованием SHA-256, или же, как он обозначен в заголовке, HS256. Для работы с этим алгоритмом нужен один секретный ключ, конкретный механизм работы рассмотрим ниже. Для справки можно также отметить, что существует и асимметричный алгоритм, который можно использовать в JWT, например, RS256. Для работы с ним требуется два ключа — открытый и закрытый. Но в данной статье рассмотрим работу с одним закрытым ключом.
Полезные данные
Перейдем наконец к полезным данным. Опять же — это JSON объект, который для удобства и безопасности передачи представляется строкой, закодированной в base64. Наглядный пример полезных данных (playload) токена может быть представлен следующей строкой:
Что в JSON формате представляет собой:
Именно здесь хранится вся полезная информация. Для данной части нет обязательных полей, из наиболее часто встречаемых можно отметить следующие:
iss — используется для указания приложения, из которого отправляется токен.
user_id — для идентификации пользователя в нашем приложении, кому принадлежит токен.
Одной из самых важных характеристик любого токена является время его жизни, которое может быть задано полем exp. По нему происходит проверка, актуален ли токен еще (что происходит, когда токен перестает быть актуальным можно узнать ниже). Как я уже упоминал, токен может помочь с проблемой авторизации, именно в полезных данных мы можем добавить свои поля, которые будут отражать возможности взаимодействия пользователя с нашим приложением. Например, мы можем добавить поле is_admin или же is_preferUser, где можем указать имеет ли пользователь права на те или иные действия, и при каждом новом запросе с легкостью проверять, не противоречат ли запрашиваемые действия с разрешенными. Ну а что же делать, если попробовать изменить токен и указать, например, что мы являемся администраторами, хотя таковыми никогда не были. Здесь мы плавно можем перейти к третьей и заключительной части нашего JWT.
Подпись
На данный момент мы поняли, что пока токен никак не защищен и не зашифрован, и любой может изменить его и тем самым нарушается вообще весь смысл аутентификации. Эту проблему призвана решить последняя часть токена — а именно сигнатура (подпись). Происходит следующее: наше приложение при прохождении пользователем процедуры подтверждения, что он тот за кого себя выдает, генерирует этот самый токен, определяет поля, которые нужны, записывает туда данные, которые характеризуют данного пользователя, а дальше с помощью заранее выбранного алгоритма (который отмечается в заголовке в поле alg токена), например HMAC-SHA256, и с помощью своего приватного ключа (или некой секретной фразы, которая находится только на серверах приложения) все данные токена подписываются. И затем сформированная подпись добавляется, также в формате base64, в конец токена. Таким образом наш итоговый токен представляет собой закодированную и подписанную строку. И далее при каждом новом запросе к API нашего приложения, сервер с помощью своего секретного ключа сможет проверить эту подпись и тем самым убедиться, что токен не был изменен. Эта проверка представляет собой похожую на подпись операцию, а именно, получив токен при новом запросе, он вынимает заголовок и полезные данные, затем подписывает их своим секретным ключом, и затем идет просто сравнение двух получившихся строк. Таким нехитрым способом, если не скомпроментировать секретный ключ, мы всегда можем знать, что перед нами все еще наш %user_name% с четко отведенными ему правами.
Время жизни токена и Refresh Token
Теперь плавно перейдем к следующему вопросу — времени жизни токена, и сопутствующей этой теме refresh token. Мы помним, что одно из важнейших свойств токена — это время его жизни. И оно совсем недолговечное, а именно 10-30 минут. Может возникнуть вопрос: а зачем такое короткое время жизни, ведь тогда придется каждый раз заново создавать новый токен, а это лишняя нагрузка на приложения. А ответ достаточно очевидный, который включает в себя и одновременно ответ на вопрос: а что делать если токен был перехвачен. Действительно, если токен был перехвачен, то это большая беда, так как злоумышленник получает доступ к приложению от имени нашего %user_name%, но так как access token является короткоживущим, то это происходит лишь на недолгий период. А дальше этот токен уже является не валидным. И именно чтобы обновить и получить новый access token нужен refresh token. Как мы знаем (или если забыли можем снова прочитать в начале) пользователь после процесса аутентификацию получает оба этих токена. И теперь по истечении времени жизни access token мы отсылаем в приложение refresh token и в ответ получаем снова два новых токена, опять же один многоразовый, но ограниченный по времени — токен доступа, а второй одноразовый, но долгоживущий — токен обновления. Время жизни refresh token вполне может измеряться месяцами, что достаточно для активного пользователя, но в случае если и этот токен окажется не валидным, то пользователю следует заново пройти идентификацию и аутентификацию, и он снова получит два токена. И весь механизм работы повторится.
Заключение
В данной статье я постарался подробно рассмотреть работу клиент-серверных приложений с токеном доступа, а конкретно на примере JSON Web Token (JWT). Еще раз хочется отметить с какой сравнительной легкостью, но в тоже время хорошей надежностью, токен позволяет решать проблемы аутентификации и авторизации, что и сделало его таким популярным. Спасибо за уделенное время.
Что такое token?
Термин token имеет много разных смыслов. Один из смыслов разъяснен в посте @Heidel, но это лишь один из смыслов, причем не самый частый.
В контексте вопроса, скорее всего, речь идет о немного другом смысле.
Под токеном понимается замещение объекта неким обозначением/идентификатором (часто просто целым числом или строкой). Например: идентификатор сессии это классический токен. Токены широко применяются обычно в системах авторизации/идентификации и проч. Технически обычно реализуются в виде записи в БД, где токен является идентификатором записи о данных юзера или предоставленного доступа. Обычно в этом случае токен вычисляется как хэш комбинации данных юзера (логина), времени создания и ключей сервера ну и проч.
Смысл всего этого в том, что вместо того, чтобы передавать юзеру целый сонм разных данных достаточно дать ему в руки токен и сказать: вот тебе токен и с помощью него можно при необходимости сделать все что надо. Это и удобно и меньше рисков засветки данных.
Токен — это нечто, чем должен обладать пользователь, чтобы получить доступ к ресурсу. Например, доступ к серверу можно организовать через файл Token.dat для каждого пользователя. Каждому пользователю нужно выдать его персональный файл Token.dat, в котором содержится полный список необходимых данных для доступа к ресурсу, например адрес и порт сервера, идентификатор пользователя и его ключ.
Лексема (token) — минимальная единица языка, имеющая самостоятельный смысл. Существуют следующие виды лексем
- имена (идентификаторы);
- ключевые слова;
- знаки операций;
- разделители;
- литералы (константы).
В общем смысле, токен — это символическая единица, представляющая какую-либо ценность или имеющая определенные права и привилегии. Вот некоторые из наиболее распространенных значений токена:
В защите информации: Токен может быть использован для идентификации и авторизации пользователя или системы. Например, при входе в систему вы можете предоставить учетные данные (такие как имя пользователя и пароль), и в ответ получить уникальный токен, который будет использоваться для идентификации вас при последующих запросах.
В блокчейн-технологиях: Токен может представлять цифровую форму активов, таких как криптовалюта или символические акции. Благодаря токенам возможно создание инновационных моделей экономических систем и криптовалютных сетей.
В программировании: Токен — это минимальная единица синтаксиса языка программирования. Код программы состоит из токенов, которые представляют ключевые слова, идентификаторы, операторы, скобки и другие элементы.