Обробка оновлення токена / закінчення сеансу в API RESTful


17

Я будую API RESTful, який використовує маркери JWT для автентифікації користувача (видається loginкінцевою точкою та надсилається після цього у всі заголовки), і маркери потрібно renewоновити через певний час (викликаючи кінцеву точку, яка повертає оновлений маркер ).

Можливо, сеанс API користувача стає недійсним до закінчення терміну дії маркера, отже, всі мої кінцеві точки починаються з перевірки того, що: 1) маркер все ще дійсний і 2) сеанс користувача все ще дійсний. Немає можливості безпосередньо визнати недійсним маркер, оскільки клієнти зберігають його локально.

Тому всі мої кінцеві точки повинні сигналізувати моїм клієнтам про дві можливі умови: 1), що настав час відновити маркер або 2) про те, що сеанс став недійсним, і вони більше не мають доступу до системи. Я можу придумати дві альтернативи для своїх кінцевих точок, щоб сигналізувати своїм клієнтам, коли виникає одна з двох умов (припустимо, що клієнти можуть бути адаптовані до будь-якого варіанту):

  1. Поверніть код http 401 (несанкціонований), якщо сеанс став недійсним або поверніть код 412 (попередня умова не вдалася), коли маркер закінчився, і настав час зателефонувати до renewкінцевої точки, яка поверне код 200 (нормально).
  2. Повернення 401 для сигналізації про те, що або сеанс недійсний, або маркер минув. У цьому випадку клієнт негайно викликає renewкінцеву точку, якщо вона повертає 200, то маркер оновлюється, але якщо renewтакож повертає 401, то це означає, що клієнт поза системою.

Яку з двох вищезазначених альтернатив ви б рекомендували? Який із них був би більш стандартним, простішим для розуміння та / або більш ВИПУСНИМ? Або ви б взагалі рекомендували інший підхід? Чи бачите ви явні проблеми чи ризики безпеки для будь-якого варіанту? Додаткові бали, якщо ваша відповідь містить зовнішні посилання, що підтверджують вашу думку.

ОНОВЛЕННЯ

Хлопці, будь ласка, зосередьтесь на реальному запитанні - яка з двох альтернатив http-коду для сигналізації про недійсне відновлення / сеанс найкраща? Не заважайте на те, що моя система використовує JWT та сеанси на сервері, це особливість мого API для дуже конкретних правил бізнесу, а не та частина, для якої я шукаю допомоги;)


Як сеанс користувача стане недійсним до закінчення терміну дії маркера, якщо припустити короткий час (приблизно 5 хвилин)?
Джек

Через бізнес-правила інша частина системи може визнати недійсним сеанс.
Оскар Лопес

1
JWT призначені для підтвердження ідентичності, оскільки в "підтверджено, що цей запит є від користувача X". Якщо у вашому бізнесі є щось на кшталт "користувачеві X більше не дозволяється взаємодіяти з ресурсом Y", це потрібно перевірити окремо від JWT.
Джек

@Jack точно! це якраз моя суть, і причина, чому мені потрібно використовувати додатковий, ефективний рівень для збереження інформації про сеанс. Простий JWT, приємний, як це може бути, просто не вирізаний для роботи.
Оскар Лопес

1
Можливо, вас зацікавить моя відповідь :)
Джек

Відповіді:


22

Це звучить як випадок аутентифікації проти авторизації .

JWT - це криптографічно підписані претензії щодо джерела запиту. JWT може містити твердження типу "Цей запит призначений для користувача X" та "User X має ролі адміністратора". Отримання та надання цього доказу за допомогою паролів, підписів та TLS є доменом аутентифікації - доказуючи, що ви є тим, ким ви кажете, що є.

Що ці претензії означають для вашого сервера - які конкретні користувачі та ролі можуть виконувати - це проблема авторизації . Різницю між ними можна описати двома сценаріями. Припустимо, Боб хоче зайти до складу обмеженого сховища на складі своєї компанії, але спочатку він повинен мати справу з охоронцем на ім'я Джим.

Сценарій А - Аутентифікація

  • Боб: "Здрастуйте, Джіме, я хотів би ввести обмежене зберігання".
  • Джим: "У вас є ваш знак?"
  • Боб: "Ні, забув".
  • Джим: "Вибачте, товариш, жоден запис без значка".

Сценарій В - Авторизація

  • Боб: "Здрастуйте, Джиме, я хотів би ввести обмежене зберігання. Ось мій знак".
  • Джим: "Ей, Бобе, для входу сюди потрібен дозвіл 2 рівня. Вибач".

Терміни придатності JWT - це пристрій аутентифікації, який використовується для запобігання крадіжкам інших людей. Якщо всі ваші JWT мають термін придатності п’ять хвилин, це не так вже й велика справа, якщо їх вкрадуть, тому що вони швидко стануть марними. Однак правило "закінчення сеансу", яке ви обговорюєте, звучить як проблема авторизації. Деяка зміна стану означає, що користувачеві X більше не дозволяється робити те, що раніше використовував. Наприклад, користувача Боба, можливо, звільнили - неважливо, що його значок говорить, що він більше є Боб, тому що просто бути Боб більше не дає йому ніяких повноважень у компанії.

Ці два випадки мають чіткі коди відповідей HTTP: 401 Unauthorizedта 403 Forbidden. На жаль, названий код 401 призначений для питань аутентифікації, таких як відсутні, втратили чинність або відкликали облікові дані. 403 призначений для авторизації, де сервер точно знає, хто ви є, але вам просто не дозволяється робити те, що ви намагаєтеся зробити. У разі видалення облікового запису користувача спроба зробити щось із JWT у кінцевій точці призведе до 403 забороненої відповіді. Однак якщо термін дії JWT закінчився, правильним результатом буде 401 Несанкціонований.

Поширена модель JWT - мати "довгоживучі" та "недовговічні" жетони. Довговічні жетони зберігаються на клієнті як короткотривалі маркери, але вони обмежені за обсягом і використовуються лише у вашій системі авторизації для отримання короткотривалих жетонів. Довгоживучі жетони, як випливає з назви, мають дуже тривалі терміни придатності - ви можете використовувати їх для запиту нових жетонів протягом днів або тижнів. Недовговічні жетони - це жетони, які ви описуєте, і використовуються з дуже короткими термінами придатності для взаємодії з вашою системою. Довговічні жетони корисні для реалізації функціоналу "Запам'ятати мене", тому вам не потрібно вводити свій пароль кожні п’ять хвилин, щоб отримати новий короткотривалий маркер.

Проблема "вимкнення сеансу", яку ви описуєте, звучить аналогічно спробі визнати недійсним довговічний JWT, оскільки недовговічні рідко зберігаються на стороні сервера, а довговічні відслідковуються у випадку, якщо їх потрібно скасувати. У такій системі спроба придбати облікові дані з анульованим довгожившим маркером призведе до 401 несанкціонованого доступу, оскільки користувач технічно може отримати облікові дані, але маркер, який вони використовують, не підходить для виконання завдання. Тоді, коли користувач намагається придбати новий маркер довгоживучого за допомогою свого імені користувача та пароля, система може відповісти 403 Заборонено, якщо їх вигнали з системи.


3
Це вказівки, які я шукав, і ви внесли дуже важливе розуміння до дискусії - що це випадок автентифікації проти авторизації, і кожен повинен розглядатися по-різному. Спасибі!
Оскар Лопес

16

Ваш сеанс API - це річ, яка взагалі не повинна існувати у світі RESTful. Операції RESTful повинні бути без громадянства, сесія містить стан і, таким чином, не має місця в світі RESTful.

JWT повинен бути вашим єдиним способом визначити, користувач все-таки має право доступу до кінцевої точки чи ні. Сеанс не повинен грати в цьому абсолютно ніякої ролі. Якщо це так, у вас немає API RESTful.

Коли ви повністю усунете сеанс, що, якщо ви прагнете API RESTful, вам слід це зробити, і використовувати тільки JWT як фактор автентифікації, користувач або має право використовувати вашу кінцеву точку, або ні - у цьому випадку 401 Unauthorizedкод відповіді підходить - і повинен зателефонувати в renewкінцеву точку з grant_type=refresh_tokenбудь-якою ідентифікацією оновлення, яке ви використовуєте.

Оновлення:

З коментаря здається, що потік перевірки JWT, який ви зараз використовуєте, невірний. Перевірка повинна виглядати приблизно так:

  Client        RESTful API      JWT Issuer
     |              |                |
     |----- 1. ---->|                | 
     |              |------ 2. ----->|-----
     |              |                | 3. |
     |              |<----- 4. ------|<----
-----|<---- 5. -----|                |
| 6. |              |                |
---->|----- 7. ---->|                |
     |              |------ 8. ----->|-----
     |              |                | 9. |
     |              |<----- 10. -----|<----
     |              |                |
     |              |------          |
     |              | 11. |          |
     |<---- 12. ----|<-----          |
     |              |                |
     .              .                .

1. Ask RESTful API for a JWT using login endpoint.
2. Ask Issuer to create a new JWT.
3. Create JWT.
4. Return JWT to the RESTful API.
5. Return JWT to Client.
6. Store JWT to append it to all future API requests.
7. Ask for data from API providing JWT as authorization.
8. Send JWT to Issuer for verification.
9. Issuer verifies JWT.
10. Issuer returns 200 OK, verification successful.
11. Retrieve and format data for Client.
12. Return data to Client.

Сервер, RESTful APIповинен перевірити дійсність маркера, який надсилається як Авторизація. Це не відповідальність Client. Схоже, ви зараз цього не робите. Здійснюйте перевірку JWT таким чином, і вам взагалі не потрібні сеанси.


Дякую за вашу відповідь. Погоджено, використання сеансу не буде стовідсотковим підходом, але як я вже згадував вище, мені потрібно заборонити доступ деяким користувачам до закінчення терміну дії маркера.
Оскар Лопес

2
@ ÓscarLópez Тоді просто недійсні маркери, які користувачі використовують. Вони більше не зможуть отримати доступ до API за допомогою наданого маркера (який тепер буде визнаний недійсним), і вам не потрібен сеанс.
Енді

1
Токени зберігаються на клієнті, як я можу їх визнати недійсними? Я повинен був би відслідковувати, які з них дійсні ... і ось там держава отримує свою некрасиву голову. Іноді це неминуче.
Оскар Лопес

Зловмисний клієнт може продовжувати надсилати раніше дійсний маркер до тих пір, поки його час закінчення дозволяє, але мені потрібно негайно вигнати його з системи - отже, встановлення короткого часу відновлення також не є можливим.
Оскар Лопес

4
@Laiv Я зробив схему послідовностей у блокноті.
Енді

1

Тож, зізнаюся, мені не має сенсу турбуватися про те, який підхід є найбільш ВІДПОВІДНИМ, коли ви вже порушуєте REST конвенції під час сесії, але я розумію, що задовольняєте ваші бізнес-вимоги.

З точки зору REST, клієнт або має автентифікацію, або їх немає. Архітектура не надто переймається, чому (це вводить непотрібний стан), тому, щоб відповісти на ваше головне питання, у мене взагалі не було б оновлення кінцевої точки. Клієнт, що ввійшов у систему, завжди просто надсилає свій JWT, і сервер завжди його підтверджує і приймає, надсилаючи відповідний код успіху на основі дії 200, 201 тощо), або відхиляє відповідним чином 401 або 403.

Тепер JWT буде пов'язаний з якимось обліковим записом. Цей обліковий запис може бути заблокований або заглушений чи що завгодно, і тому сам маркер може бути дійсним, але дію все одно відхилено в іншому місці. Якщо справа в тому, що обліковий запис користувача заблоковано через правила ведення бізнесу, то це все-таки 401 або 403, залежно від того, скільки інформації ви хочете надати клієнту (різні підприємства мають різні думки щодо цього).

Нарешті, якщо ви стверджуєте, що обліковий запис може бути розблокований та дійсний, але JWT просто потрібно відкликати, я б ВІДПОВІСТИ дотримуватися 401 або 403 і вести щось на зразок списку відкликань сертифікатів недійсних JWT, які ви можете помістити в нього , до тих пір, поки він очиститься, коли термін дії JWT закінчився (у більшості баз даних це можна зробити, або у вас є події в коді програми).


jwt мають на меті бути без громадянства. в момент, коли ви ставите під сумнів його вміст і підтверджуєте його проти db, він більше не є без громадянства, тому він стає зайвим, оскільки є кращі рішення для державних сесій
Stavm,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.