Призначення та вимоги
Генерація токенів доступу у форматі JWT реалізована для зменшення навантаження на службу mithril, яка існує під час будь-якого виклику API eHealth, який використовує заголовок авторизації з токеном доступу.
У форматі JWT можна використовувати лише токени доступу, які використовуються для отримання доступу до кінцевих точок електронної охорони здоров’я (наприклад, створення/оновлення запиту особи, створення запиту на декларацію, отримання відомостей про підтвердження особи тощо). Будь-які інші токени, які використовуються в потоці OAuth (тобто авторизаційний_код, refresh_token, session_token), усе ще генеруються в існуючому форматі.
Формат створення токену доступу контролюється параметром конфігурації - ACCESS_TOKEN_JWT.
Перевірка існуючого формату генерації токену доступу має бути активною та робочою.
Токен доступу у форматі JWT містить лише дані, пов’язані з користувачами та клієнтами, дані брокера все ще перевіряються за допомогою перевірки API-ключа через службу Mithril за допомогою існуючого процесу, описаного тут MIS authorization
Маркери доступу у форматі JWT не зберігаються в базі даних mithril, оскільки вони перевіряються лише на стороні служби Kong.
Впровадження
Генерація токену доступу в форматі JWT
Наступні методи використовуються для генерації токену доступу для користувача:
RC Exchange oAuth Code Grant to Access Token
/wiki/spaces/PCAB/pages/17415667759
/wiki/spaces/PCAB/pages/17415798881
/wiki/spaces/PCAB/pages/17415340883
/wiki/spaces/PCAB/pages/17416060933
Методи перевіряють значення конфігураційного параметру ACCESS_TOKEN_JWT:
true - маркери доступу для користувачів генеруються у форматі JWT;
false - маркери доступу для користувачів генеруються в непрозорому форматі (захешований рядок запису в базі даних mithril, таблиця
tokens
).
Відповіді методів для згенерованого токену не змінено, токен усе ще повертається в полі value
.
Структура JWT
Токен доступу в форматі JWT складається з трьох закодованих base64 рядків, які розділені символом dot:
Header
Payload
Signature
Хедер
Хедер JWT містить наступні поля:
Поле | Опис | Приклад |
---|---|---|
| підпис або алгоритм шифрування, який використовується для створення JWT |
|
| ідентифікатор закритого ключа, який використовується для підпису JWT |
|
| тип токену |
|
Сервіс Mithril використовує RS512
JWT алгоритм підпису з типом токену JWT
.
Пейлоад
Пейлоад JWT містить наступні поля:
Поле | Опис | Приклад |
---|---|---|
| audiene (для кого або для чого призначений токен) |
|
| термін дії токена та час у форматі unix |
|
| дата і час генерації токена в unix-форматі |
|
| маркер недійсний до дати й часу у форматі unix |
|
| унікальний ідентифікатор маркера у форматі uuid |
|
| предмет маркера (user_id) у форматі uuid |
|
| назва емітенту токену |
|
| тип доступу клієнта, якщо BROKER - потрібна додаткова перевірка api-ключа, якщо DIRECT - перевірка api-ключа не потрібна |
|
| identifier of approval between user, applicant user and client that was used to issue access token |
|
| ідентифікатор користувача, який ініціював створення токену доступу для суб’єкта (користувача) у форматі uuid |
|
| ідентифікатор особи у форматі uuid, який пов’язаний з користувачем, який ініціював генерацію токену доступу для суб’єкта (користувача), якщо існує |
|
| ідентифікатор клієнта, який ініціював генерацію токену доступу для суб’єкта (користувача) у форматі uuid |
|
| тип дозволу, який використовувався для видачі токену доступу, якщо існує |
|
| ідентифікатор особи у форматі uuid, пов’язаний із суб’єктом токену (користувачем), якщо такий існує |
|
| uri перенаправлення, який використовувався клієнтом для створення токену доступу, якщо існує |
|
| токен оновлення, створений за допомогою маркера доступу |
|
|
|
|
| тип токену |
|
Сервіс Mithril формує поле пейлоад на основі даних, що використовуються для генерації токену (user_id, client_id, перелік запитаних скоупів, токен сессії, etc).
Підпис
Підпис JWT містить підпис вмісту токену з використанням алгоритму, описаного в полі alg із заголовка.
Служба Mithril використовує асиметричний алгоритм підпису – вміст маркера підписується за допомогою закритого ключа, який зберігається в параметрі JWT_PRIVATE_KEY.
Перевірка токену доступу в форматі JWT
Токен доступу у форматі JWT потрібно надіслати в той самий заголовок авторизації для будь-якого методу, який вимагає токен доступу.
Токени доступу у форматі JWT перевіряються лише службою Kong, якщо пройдено всі перевірки токенів – список скоупів з поля scope
використовується для перевірки доступу до запитуваного методу.
JWT перевіряється згідно наступних кроків:
Перевірити формат заголовку авторизації
якщо токен передається в JWT – перевірити, що це JWT
в іншому випадку – перевірте його за допомогою перевірки існуючого формату токену (згідно перевірки токену методом mithril)
Перевірити підпис JWT з публічним ключем, який зберігається в параметрах JWT_PUBLIC_KEY та JWT_PUBLIC_KEY_OLD
в разі, якщо підпис JWT не перевірено по збереженому публічному ключу - повернути 401 ('access_denied')
Перевірити строк дії токену по полю
exp
, що значення більше ніж now()в разі, якщо поле
exp
не існує або дата закінчення строку в минулому - повернути 401 ('access_denied')
Перевірити, що емітент в полі
iss
рівний значенню ‘EHeath’в разі, якщо поле
iss
не існує або містить будь-які інші дані - повернути 401 ('access_denied')
Перевірити, що audience токену з поля aud рівне значенню ‘EHealth’
в разі, якщо поле
aud
не існує або містить будь-які інші дані - повернути 401 ('access_denied')
Перевірити, що токен не входить до чорного списку в базі даних кешу Redis за значеннями полів із пейлоад (jti, sub, client_id):
перевірити, що ключ blacklist_jti_<<jti>> не існує (наприклад,
blacklist_jti_481aa86b-7bfa-462c-8bcb-1a9e9edff192
);перевірити, що ключ blacklist_user_id_<<sub>> не існує (наприклад,
blacklist_user_id_481aa86b-7bfa-462c-8bcb-1a9e9edff192
);перевірити, що ключ blacklist_client_id_<<client_id>> не існує (наприклад,
blacklist_client_id_8a99ffdf-314e-4419-931d-a76f41f8c456
);перевірити, що ключ blacklist_user_id_client_id_<<sub>>_<<client_id>> не існує (напраклад,
blacklist_user_id_client_id_481aa86b-7bfa-462c-8bcb-1a9e9edff192_8a99ffdf-314e-4419-931d-a76f41f8c456
);якщо будь-який із ключів існує в базі даних кешу Redis - повернути 401 ('access_denied')
перевірити, що ключ blacklist_app_id_<<app_id>> не існує (для прикладу,
blacklist_app_id_ce21628e-317b-4edb-bda6-0de661f24666
);якщо будь-який із ключів існує в базі даних кешу Redis - повернути 401 ('access_denied')