jwt


Представляю вам мой довольно вольный перевод статьи 5 Easy Steps to Understanding JSON Web Tokens (JWT). В этой статье будет рассказано о том, что из себя представляют JSON Web Tokens (JWT) и с чем их едят. То есть какую роль они играют в проверке подлинности пользователя и обеспечении безопасности данных приложения.


Для начала рассмотрим формальное определение.


JSON Web Token (JWT) — это JSON объект, который определен в открытом стандарте RFC 7519. Он считается одним из безопасных способов передачи информации между двумя участниками. Для его создания необходимо определить заголовок (header) с общей информацией по токену, полезные данные (payload), такие как id пользователя, его роль и т.д. и подписи (signature).
Кстати, правильно JWT произносится как /d??t/

Простыми словами, JWT — это лишь строка в следующем формате header.payload.signature.
Предположим, что мы хотим зарегестрироваться на сайте. В нашем случае есть три участника — пользователь user, сервер приложения application server и сервер аутентификации authentication server. Сервер аутентификации будет обеспечивать пользователя токеном, с помощью которого он позднее сможет взаимодействовать с приложением.


Как приложение использует JWT для проверки аутентификации пользователя.


Приложение использует JWT для проверки аутентификации пользователя следующим образом:


  1. Сперва пользователь заходит на сервер аутентификации с помощью аутентификационного ключа (это может быть пара логин/пароль, либо Facebook ключ, либо Google ключ, либо ключ от другой учетки).
  2. Затем сервер аутентификации создает JWT и отправляет его пользователю.
  3. Когда пользователь делает запрос к API приложения, он добавляет к нему полученный ранее JWT.
  4. Когда пользователь делает API запрос, приложение может проверить по переданному с запросом JWT является ли пользователь тем, за кого себя выдает. В этой схеме сервер приложения сконфигурирован так, что сможет проверить, является ли входящий JWT именно тем, что был создан сервером аутентификации (процесс проверки будет объяснен позже более детально).

Структура JWT


JWT состоит из трех частей: заголовок header, полезные данные payload и подпись signature. Давайте пройдемся по каждой из них.


Шаг 1. Создаем HEADER


Хедер JWT содержит информацию о том, как должна вычисляться JWT подпись. Хедер — это тоже JSON объект, который выглядит следующим образом:


header = { "alg": "HS256", "typ": "JWT"}

Поле typ не говорит нам ничего нового, только то, что это JSON Web Token. Интереснее здесь будет поле alg, которое определяет алгоритм хеширования. Он будет использоваться при создании подписи. HS256 — не что иное, как HMAC-SHA256, для его вычисления нужен лишь один секретный ключ (более подробно об этом в шаге 3). Еще может использоваться другой алгоритм RS256 — в отличие от предыдущего, он является ассиметричным и создает два ключа: публичный и приватный. С помощью приватного ключа создается подпись, а с помощью публичного только лишь проверяется подлинность подписи, поэтому нам не нужно беспокоиться о его безопасности.


Шаг 2. Создаем PAYLOAD


Payload — это полезные данные, которые хранятся внутри JWT. Эти данные также называют JWT-claims (заявки). В примере, который рассматриваем мы, сервер аутентификации создает JWT с информацией об id пользователя — userId.


payload = { "userId": "b08f86af-35da-48f2-8fab-cef3904660bd" }

Мы положили только одно заявку (claim) в payload. Вы можете положить столько заявок, сколько захотите. Существует список стандартных заявок для JWT payload — вот некоторые из них:


  • iss (issuer) — определяет приложение, из которого отправляется токен.
  • sub (subject) — определяет тему токена.
  • exp (expiration time) — время жизни токена.

Эти поля могут быть полезными при создании JWT, но они не являются обязательными. Если хотите знать весь список доступных полей для JWT, можете заглянуть в Wiki. Но стоит помнить, что чем больше передается информации, тем больший получится в итоге сам JWT. Обычно с этим не бывает проблем, но все-таки это может негативно сказаться на производительности и вызвать задержки во взаимодействии с сервером.


Шаг 3. Создаем SIGNATURE


Подпись вычисляется с использование следующего псевдо-кода:


const SECRET_KEY = 'cAtwa1kkEy'
const unsignedToken = base64urlEncode(header) + '.' + base64urlEncode(payload)
const signature = HMAC-SHA256(unsignedToken, SECRET_KEY)

Алгоритм base64url кодирует хедер и payload, созданные на 1 и 2 шаге. Алгоритм соединяет закодированных строки через точку. Затем полученная строка хешируется алгоритмом, заданным в хедере на основе нашего секретного ключа.


// header eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
// payloadey J1c2VySWQiOiJiMDhmODZhZi0zNWRhLTQ4ZjItOGZhYi1jZWYzOTA0NjYwYmQifQ
// signature -xN_h82PHVTCMA9vdoHrcZxH-x5mb11y1537t3rGzcM

Шаг 4. Теперь бъединим все три JWT компонента вместе


Теперь, когда у нас есть все три составляющих, мы можем создать наш JWT. Это довольно просто, мы соединяем все полученные элементы в строку через точку.


const token = encodeBase64Url(header) + '.' + encodeBase64Url(payload) + '.' + encodeBase64Url(signature)
// JWT Token
// eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJiMDhmODZhZi0zNWRhLTQ4ZjItOGZhYi1jZWYzOTA0NjYwYmQifQ.-xN_h82PHVTCMA9vdoHrcZxH-x5mb11y1537t3rGzcM

Вы можете попробовать создать свой собственный JWT на сайте jwt.io.
Вернемся к нашему примеру. Теперь сервер аутентификации может слать пользователю JWT.


Как JWT защищает наши данные?


Очень важно понимать, что использование JWT НЕ скрывает и не маскирует данные автоматически. Причина, почему JWT используются — это проверка, что отправленные данные были действительно отправлены авторизованным источником. Как было продемонстрировано выше, данные внутри JWT закодированы и подписаны, обратите внимание, это не одно и тоже, что зашифрованы. Цель кодирования данных — преобразование структуры. Подписанные данные позволяют получателю данных проверить аутентификацию источника данных. Таким образом закодирование и подпись данных не защищает их. С другой стороны, главная цель шифрования — это защита данных от неавторизованного доступа. Для более детального объяснения различия между кодированием и шифрованием, а также о том, как работает хеширование, смотрите эту статью. Поскольку JWT только лишь закодирована и подписана, и поскольку JWT не зашифрована, JWT не гарантирует никакой безопасности для чувствительных (sensitive) данных.


Шаг 5. Проверка JWT


В нашем простом примере из 3 участников мы используем JWT, который подписан с помощью HS256 алгоритма и только сервер аутентификации и сервер приложения знают секретный ключ. Сервер приложения получает секретный ключ от сервера аутентификации во время установки аутентификационных процессов. Поскольку приложение знает секретный ключ, когда пользователь делает API-запрос с приложенным к нему токеном, приложение может выполнить тот же алгоритм подписывания к JWT, что в шаге 3. Приложение может потом проверить эту подпись, сравнивая ее со своей собственной, вычисленной хешированием. Если подписи совпадают, значит JWT валидный, т.е. пришел от проверенного источника. Если подписи не совпадают, значит что-то пошло не так — возможно, это является признаком потенциальной атаки. Таким образом, проверяя JWT, приложение добавляет доверительный слой (a layer of trust) между собой и пользователем.


В заключение


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


Полезные ссылки


  1. 5 Easy Steps to Understanding JSON Web Tokens (JWT)
  2. Securing React Redux Apps With JWT Tokens
  3. Зачем нужен Refresh Token, если есть Access Token?

Комментарии (58)


  1. smple
    15.10.2017 23:12

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


    1. umputun
      16.10.2017 06:07

      Нет, смысл вовсе не в этом. Строго говоря «application server может читать данные из payload без ключа» — это очень плохая идея. Никакого доверия таким данным нет и их можно использовать только после того, как сделана проверка подписи. Это действительно делает application server и он делает это на каждый запрос в котором JWT представлен.

      Какой-то ключ application server должен знать, но это не обязательно должен быть тот же секрет, который использовался при создании токена. А может быть и тот-же, зависит от Signing Method — HMAC (shared key) или RSA/ECDSA (asymmetric).


      1. smple
        16.10.2017 17:54

        давай те по порядку.
        В статье говориться что секрет это то с помощью чего подписывается, далее в статье упоминается что секрет знают и сервер авторизации и сервер приложений, я лишь подчеркнул что это не правильно
        Если подпись идет с помощью rsa то там ПУБЛИЧНЫЙ (не секретный) ключ и его может знать вообще кто угодно, а приватный ключ у сервера авторизации останется, как описали в коменте ниже.
        При этом больше замечаний к статье не имею и в целом она очень адекватно написана, я лишь указал на то что неправильно трактовать можно прочитав статью


        1. umputun
          16.10.2017 19:10

          это вполне вполне правильная трактовка. HMAC именно так (общий секрет) и работает.


          1. smple
            16.10.2017 20:41

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


            в примере в статье речь о симметричном шифрование и секрет получается один и тот же что на auth сервисе, что на application.


            1. umputun
              16.10.2017 20:52

              > в примере в статье речь о симметричном шифрование и секрет получается один и тот же что на auth сервисе, что на application.

              да, именно об этом и идет речь в статье. И это, повторю в 3й раз, вполне правильная трактовка. С точки зрения JWT нет ничего неправильного в использовании симметричного ключа, это один из легальных способов.

              Что касается «удобней» — это уже вопрос к вашей системе. Я могу придумать случаи когда использование HMAC будет удобней, но суть не в этом, а в том, что это один из нормальных методов подписи и верификации JWT.


              1. smple
                16.10.2017 21:06

                я не говорю что HMAC или все симетричное шифрование это плохо и не правильно, я говорю что в приведенной в статье примере с сервисом авторизации и application, использовать один секрет не стоит, особенно если существуют и другие сервисы которые доверяют сервису авторизации, потому что это не безопасно не с точки зрения jwt, а скорее здравого смысла.


                1. umputun
                  16.10.2017 21:11

                  эээ… а это что? «я лишь подчеркнул что это не правильно...», «вы не правильно пишите что application server должен знать секрет ...»

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


                  1. smple
                    16.10.2017 21:24

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


            1. medvedevia
              17.10.2017 00:13

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

              Зато симметричное шифрование гораздо быстрее асимметричного.


        1. TheDaemon
          16.10.2017 19:48
          +1

          Все правильно в статье написано. В статье взят пример с HMAC'ом, а он на симметричном ключе. Симметричный ключ может быть безопасно расшарен между двумя участниками (сервер аутентификации и сервер приложений), например с использованием side-channel (на флешке) или по защищенному другими ключами каналу.
          Вы пишете в первом сообщении, что сервер приложений сам проверить токен не может. Это полностью убивает сам смысл подписи токенов, так как сервер аутентификации может проверять валидность выданных им токенов и без криптографии, просто храня все выданные токены в БД.
          Публичный ключ тоже требует защиты, правда не от узнавания, а от подделки. Поэтому и придумали PKI.


          1. smple
            16.10.2017 20:35
            +1

            еще раз по порядку.
            в случае если у вас несколько сервисов и один и тот же ключ используется во всех сервисах и доступен он между сервисами, если злоумышленник получит доступ к одному из сервисов, он сможет получить доступ к ключу, а с помощью ключа он сможет генерировать какие угодно токены, чем больше сервисов знает общий секрет, тем выше шансы на компрометацию.
            В такой ситуации безопасней чтобы сервисы для валидации токена обращались к сервису авторизации и он уже проверял валидный он или нет, тем самым получив доступ к другим сервисам, они не смогут выпускать произвольные токены, а более правильно это ассимитричное шифрование, как человек тоже написал ниже, что есть приватный ключ и он известен в одном месте(в котором выдают токены), остальные сервисы знают только ПУБЛИЧНЫЙ ключ, с помощью которого могу проверять подписи, это публичный ключ можно хоть всему миру рассказать, главное что для генерация токена надо приватный ключ.


  1. alek_sys
    15.10.2017 23:16

    Хороший обзор, спасибо.


    только сервер аутентификации и сервер приложения знают секретный ключ

    Cекретный ключ они знают только если сервер аутентификации это и есть сервер приложения (т.е. это физически одно и то же приложение), если же они разные — то скорее будет использована пара private / public key. Вряд ли сервер аутентификации будет смело делиться со всеми серверами приложений своим приватным ключом.


    1. VolCh
      16.10.2017 23:02

      Речь идёт о симметричной схеме подписи, с одним ключом.


  1. Legion21
    16.10.2017 06:44

    Печально что многие не вдупляют… Автору респект ;)


  1. motomac
    16.10.2017 08:49

    По-моему, не сказано главного — чем оно лучше традиционных токенов.

    Ответ: ресурсному серверу больше нет нужды стучаться в авторизационный сервер за проверкой валидности токена и его правами при каждом запросе от клиента. Он теперь в силах сам относительно дёшево проверить и валидность, и получить доп. информацию (например, права доступа) из самого токена. JWT гарантирует их аутентичность. Т.е. имеем упрощение серверной архитектуры и уменьшение нагрузки на авторизационный сервер.


    1. andreymal
      16.10.2017 11:24
      +1

      В контексте данного ответа меня всегда интересовал вопрос: как быть, если токеном завладел злоумышленник и его нужно срочно сделать недействительным до истечения его срока годности? Или, другими словами, как реализовывать кнопочку на сайте «Завершить такую-то сессию» / «Завершить все сессии, кроме текущей»? Если сервер никуда не стучится, как он узнает, что токен недействителен?

      UPD: ой, тред не читай @ сразу отвечай, ниже то же самое спросили


      1. vlsinitsyn
        16.10.2017 13:05

        Надо делать короткое время жизни токена, несколько минут.


        1. andreymal
          16.10.2017 13:09

          Если отдавать такой токен конечному пользователю, это будет тотальное неюзерфрендли. Перезагрузил комп после обновления винды — всё, заново логиниться? Разве что использовать его по схеме от fuCtor ниже, но тогда для большинства сайтов JWT оказывается бесполезен.


          1. vlsinitsyn
            16.10.2017 13:20

            Конечному пользователю токен хранить не надо. Конечный пользователь получает и обновляет регулярно токен от authorisation sever.


            1. andreymal
              16.10.2017 13:32

              JWT выглядит всё более и более бесполезным. Если в итоге всё равно надо логиниться каждые несколько секунд минут (refresh token ведь тоже однажды протухнет? Или я чего-то не понимаю?), то тогда почему бы не тупо посылать пароль (или другую информацию для логина) в каждом запросе, благо HTTPS это безопасно позволяет?)

              Или существуют случаи, когда «authorisation sever» и сервер, читающий и проверяющий JWT — не один и тот же сервер? Я с таким ещё ни разу не сталкивался. (Не считая кучки микросервисов, спрятанных за некой единой точкой входа — тогда можно применить схему от fuCtor ниже, и JWT для пользователя опять бесполезен)


              1. vlsinitsyn
                16.10.2017 13:41

                Мы используем oAuth2 JWT от MS Azure для доступа к нашим API. Все как часики и с пол пинка. Можно даже не использовать refresh token. MS поставляет JS библиотеку которая обходится без refresh token, если есть такая необходимость. Для например SPA все замечательно. Пока есть сессия — токен автоматически, невидимо для пользователя, обновляется.


                1. andreymal
                  16.10.2017 13:43

                  Винда запустила обновление, все приложения закрыты минут десять — всё, сессия успела протухнуть, логинимся заново?


                  1. vlsinitsyn
                    16.10.2017 13:48

                    Если вы говорите об SPA, то естественно, если браузер был закрыт и сессии убиты, то пользователю заново надо будет пройти аутентификацию.


                    1. andreymal
                      16.10.2017 13:52

                      Вот это и грустно и основная причина, почему лично я не использую JWT


                      1. vlsinitsyn
                        16.10.2017 13:57

                        Хм, так а какая альтернатива? Вы предлагаете восстанавливать сессии? А как с безопасностью?
                        К JWT это вообще отношения не имеет. Если безопасность не проблема — восстанавливайте сессии с authorisation server по куки (или еще как нибудь) невидимо для пользователя и открывайте ему сразу страницу его банковского счета, например.


                        1. andreymal
                          16.10.2017 14:16

                          Банковские счета это отдельная история, о которой и говорить нужно отдельно, большинство сайтов не являются банками :)

                          От обычного сайта обычный пользователь будет требовать, чтобы его не разлогинивало. Из-за этого безопасность с короткоживущими токенами СНИЖАЕТСЯ: для постоянного автоматического релогина потребуется хранить пароль (или аналогичную инфу (refresh token?)) в открытом виде где-то рядом с токеном, и его с радостью уведёт злоумышленник вместе с токеном (mitm в эпоху повсеместного https почти нереален, скорее всего будет какой-нибудь RCE/XSS или тупо физический доступ к устройству). Придётся везде менять все пароли, похожие на утёкший. А вот если злоумышленнику попадёт классический долгоживущий токен, то достаточно будет просто удалить его из списка действительных.

                          Буду рад узнать, что я в чём-то не прав.


                          1. andreymal
                            16.10.2017 14:28

                            Окей, я придумал пользу от JWT: список недействительных токенов скорее всего будет намного меньше, чем список действительных, что позволит сэкономить место. Но больше как-то не придумывается (не считая банков, это отдельная история)


                            1. andreymal
                              16.10.2017 17:35

                              Хотя нет, так тоже не прокатит. Злоумышленник может удалить токен с места утечки (почистить localStorage, например), и тогда в список недействительных токенов добавлять окажется нечего. Придётся всё равно где-то хранить список действительных токенов. В общем, для меня JWT — штука бесполезная)


                          1. vlsinitsyn
                            16.10.2017 14:29

                            Идея refresh token — это идея oAuth2, а не JWT.
                            И как раз этот токен предназначен для того, чтобы пользователю не приходилось вводить пароль снова и снова.
                            Никто не мешает вам сделать JWT токен долгоживущим, если вы по какой-то странной причине считаете это нужным.
                            Никто не запрещает вам добавить проверку JWT токена в черном списке, как я сказал выше.
                            Разница и профит в том, что вам не надо напрягать сервер авторизации для такой проверки.
                            Но вообще говоря, короткоживущий токен рекомендуется в oAuth2 вообще и вне зависимости от механизма валидации.


                            1. andreymal
                              16.10.2017 14:34

                              Если честно, я с refresh token'ами работал мало и не до конца их понимаю, не могли бы вы пояснить — если злоумышленник утащит основной токен, то скорее всего где-то рядом он сможет взять и refresh token (если это не mitm), и тогда он просто будет продолжать получать новые токены по этому refresh token'у, что окажется эквивалентно простому долгоживущему токену; я что-то упускаю в описанной схеме или так и есть?

                              Алсо, я вроде где-то читал, что refresh token отдавать юзеру вообще нельзя, что лишь добавляет путаницы в моём понимании


                              1. vlsinitsyn
                                16.10.2017 14:43

                                refresh token не передается сервису и т.о. он более безопасный. Компрометация refresh tokenа сама по себе еще не обязательно приведет к возможности получения злоумышленником новых токенов. Зависит от того, какой механизм используется для передачи токена клиенту.


                                1. umputun
                                  16.10.2017 22:20

                                  > Компрометация refresh tokenа сама по себе еще не обязательно приведет к возможности получения злоумышленником новых токенов

                                  Вот это мне непонятно. Какой механизм может этому помешать? Передача рефреш токена, как бы она не просиходила, будет идти от клиента к серверу auth и в ответ на валидный refresh token auth server радостно создаст новый access token. Кроме условного «усиления refresh token» путем добавления туда чего-то типа source ip и/или агента или еще нечто в таком роде, я не вижу какой тут механизм помешает.


                                  1. vlsinitsyn
                                    16.10.2017 22:37

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


                                    1. umputun
                                      16.10.2017 22:45

                                      ничего не понял. кем отправлятся? что именно слушает клиент? что значит назад?

                                      Насколько я себе представляю, этот рефреш токен должен быть у клиента и получит он его в момент login, вместе с access token, где его, теоретически можно украсть, например если есть физический доступ к компьютеру жертвы. Потом он (клиент) его будет время от времени посылать auth серверу для получения нового access token. Я не вижу как в этой схеме помешать злодею который завладел этим refresh token.


                                      1. vlsinitsyn
                                        18.10.2017 02:17

                                        Зависит от вашего сценария.
                                        1.Если у вас конфиденциальный клиент, то можно требовать отправки client_id и client_secret вместе с refresh token для получения нового токена доступа. Т.о. если злоумышленник не знает вашего секрета, то получить новый токен доступа он не сможет.
                                        2. На публичном клиенте, если злоумышленник знает client_id и refresh token — то это все что ему нужно :-).


      1. motomac
        16.10.2017 13:14

        Срочно не получится. Выход один: делать время жизни JWT-токенов короткой и использовать refresh-токены.


        1. vlsinitsyn
          16.10.2017 14:03

          Если действительно надо, то никто не мешает добавить в процедуру валидации токена проверку его наличия в каком нибудь централизованном черном списке, если это необходимо.


          1. motomac
            16.10.2017 19:47

            Это уже будет обращение в хранилище, от которого мы хотели отказаться. В таком случае ничего не мешает обращаться в это хранилище за обычными токенами.


            1. vlsinitsyn
              16.10.2017 22:18

              Разница в том, что это будет обращение к внутреннему хранилищу, а не к внешнему серверу авторизации.
              Но, да, я согласен, это чисто теоретический и излишне параноидальный сценарий.
              Я считаю, что делать токен короткоживущим достаточно. Т.к. за то время, пока вы узнаете, что токен скомпрометирован и добавите его в некий список, он уже скорее всего устареет в любом случае.


            1. VolCh
              16.10.2017 23:28

              Хранилище чёрного списка может быть гораздо более быстрое, вплоть до нахождения в оперативной памяти адресного пространства сервера приложений.


        1. VolCh
          16.10.2017 23:26

          Ещё два:


          • блочить пользователя целиком до истечения токена
          • вести чёрный список


      1. vsb
        16.10.2017 16:51

        Никак, весь смысл этих токенов в отсутствии состояния. Если вам нужен такой функционал, правильно использовать традиционные варианты со списком сессий на сервере.


  1. igorp1024
    16.10.2017 09:27

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


    1. fuCtor
      16.10.2017 10:41

      Но в тоже время его можно использовать и в следующе схеме:
      — есть два контура внешний и внутренний
      — снаружи токен = oauth2 токен, со всеми плюшками, а внутри ходит JWT.
      — при проверки oauth2 токена получаем короткоживущий JWT
      — всё общение внутри уже идет используя именно JWT

      Как результат на каждый запрос сервер авторизации запрашивается лишь раз, а остальные микросервисы довольствуются лишь данными из JWT, в принципе в подавляющем числе случаев достаточно UserID и набора прав.


    1. flatscode
      16.10.2017 16:51

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

      Т.к. размер этот базы на практике будет небольшим, а элементы в ней относительно короткоживущими (не сильно дольше времени жизни токена), то вполне можно сделать весьма быструю эффективную ее реализацию.


    1. VolCh
      16.10.2017 23:34

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


  1. UncleAndy
    16.10.2017 11:39

    У меня есть вопрос. Возможно глупый. Каким образом токен JWT защищен от перехвата третьей стороной?


    1. motomac
      16.10.2017 13:18

      Так же как и обычный токен (никак).


    1. flatscode
      16.10.2017 17:06

      Каким образом токен JWT защищен от перехвата третьей стороной?

      Использованием https.


  1. dissdoc
    16.10.2017 13:06

    Поясните, пожалуйста, такой кейс. В JWT я увидел неприятную особенность. Если я у пользователя украду JWT-токен, то получается я могу под именем пользователя везде заходить. Каким-то образом можно обеспечить безопасность? Подпись конкретного браузера? или как это реализуется?


    1. vlsinitsyn
      16.10.2017 13:11

      Отличие токена от пароля, в данном контексте, только в том, что токен короткоживущий.


    1. andreymal
      16.10.2017 13:14

      Разве что привязка к IP-адресу. Всё остальное при желании можно подделать. Причём касается это не только JWT, но и любых других токенов и кук. Но так как пользователь часто меняет IP и привязка к нему тоже будет неюзерфрендли, в итоге я не знаю ни одной реализации (хоть JWT, хоть не JWT), которая была бы защищена от подобных вещей (ну, помимо короткоживущих токенов, которые так любит vlsinitsyn)


      1. vlsinitsyn
        16.10.2017 13:34

        При чем тут «так любит»? Вы сами признали что альтернативы нет. IP фильтрация лишь дополняет механизм валидации, а не заменяет его. Это даже не вопрос JWT, а любого oAuth2 токена. Т.к. даже если вы будете валидировать токен через внешний сервер, результаты этой валидации обычно кэшируются на сервере на некоторое время сравнимое со временем жизни JWT.


      1. OlegOleg1980
        17.10.2017 19:45

        Привязка к ip на самом деле не так уж и «неюзерфрендли», как вы говорите. И, если подумать, то будет правильным, если смена сессии и смена ip будет происходить в один и тот же момент времени.
        К примеру, ip изменился, а сессия осталась та же. Почему изменился ip? Вариантов ответа несколько, часть из них совсем «неюзерфрендли», а даже скорее «хакераттакли». Поэтому привязка JWT к ip в несложных случаях повысит безопасность на достаточно много процентов.


        1. andreymal
          17.10.2017 19:49

          Почему изменился ip?

          Телефон поймал вайфай и подключился к нему, отключив мобильный интернет. А я набираю этот комментарий. Если в это время меня ВНЕЗАПНО разлогинит из-за всего лишь подключения вайфая — телефон с большой скоростью устремится в сторону пола.


  1. Luckyland
    17.10.2017 19:48

    Мне одному показалось что 'algorithm' в const algorithmSECRET_KEY = 'cAtwa1kkEy' лишний?


    1. borisyuzhakov Автор
      17.10.2017 19:49

      Спасибо, Luckyland. Это была опечатка.