Как определить вошедшего пользователя из Keycloak OpenID logout_token при выходе из обратного канала?
Сначала позвольте мне описать установку:
У нас есть frontend продукт на базе Angular от другой команды клиентов (не часть кода, который мы можем легко модифицировать), и backend API сервер на базе django.
Внешняя сторона регистрируется на сервере keycloak, и когда она зарегистрирована, внутренняя сторона получает заголовок Auth с маркером предъявителя в каждом запросе. Из этого мы можем идентифицировать вошедшего пользователя следующим образом (используя python-keycloak):
ret = keycloak.userinfo(bearer_token)
username = ret['preferred_username']
Это, очевидно, очень расточительно, поскольку каждый раз требуется дополнительный сетевой запрос к keycloak - поэтому вместо этого мы создаем сессию пользователя django и используем ее для управления сессиями.
Теперь, когда дело доходит до выхода из системы, когда пользователь выходит из фронт-энда, нам нужно аннулировать сессию django.
Я настроил "Back channel logout URL" в настройках keycloak realm для вызова некоторой конечной точки на сервере django. Конечная точка вызывается при выходе из системы и получает значение "logout_token" в аргументах.
Теперь я не уверен, как я должен определить, какой пользователь выходит из системы, основываясь на этом токене. Как это можно сделать?
Заранее спасибо...
Я не уверен на 100% в правильности вашей архитектуры. Тем не менее, что касается вашего конкретного вопроса:
ret = keycloak.userinfo(bearer_token)
username = ret['preferred_username']
Из книги "Ключ плаща" :
preferred_username Это имя пользователя, прошедшего аутентификацию. Вам следует избегать этого в качестве ключа для пользователя, так как оно может быть изменено и даже ссылаться на другого пользователя в будущем. другого пользователя в будущем. Вместо этого всегда используйте вложенное поле для ключ пользователя.
Из спецификации OpenID connect specification можно прочитать, что:
OPs посылают JWT, похожий на ID Token, RPs, называемый Logout Token, чтобы запросить, чтобы они вышли из системы. ID Токены определены в Разделе 2 [OpenID.Core].
В токене выхода из системы используются следующие утверждения:
iss REQUIRED. Идентификатор эмитента, (...)
sub OPTIONAL. Идентификатор субъекта,(...)
aud REQUIRED. Аудитория(и), (...)
iat REQUIRED. Выдается в момент, (...)
jti REQUIRED. Уникальный идентификатор для токена, (...) (...) sid OPTIONAL. Идентификатор сессии - строковый идентификатор сессии. Представляет собой сеанс пользовательского агента или устройства для вошедшего в систему конечного пользователя на RP. (..)
Токен выхода ДОЛЖЕН содержать либо sub, либо sid Claim, и МОЖЕТ содержать оба. Если sid Claim не присутствует, то предполагается, что все сессии на RP для конечного пользователя, идентифицированного iss и sub Claims, будут выведены из системы.
.
Поэтому вы можете попробовать использовать утверждение 'sub', которое является уникальным идентификатором аутентифицированного пользователя. Вам (вероятно) потребуется создать связку между 'sub' и 'user' в вашем бэкенде. В качестве альтернативы, вы можете использовать ту же логику, но вместо этого применить ее к 'sid'. Там вы сопоставите ID сессии Keycloak с вашей собственной ID сессией.
Однако, мой вопрос таков:
Фронтэнд входит на сервер keycloak, и когда он входит в систему, бэкэнд получает заголовок Auth с токеном предъявителя в каждом запросе. бэкэнд получает заголовок Auth с токеном предъявителя в каждом запросе.
Из этого токена предъявителя (который, как я предполагаю, является токеном доступа) вы не можете просто получить 'preferred_username' (или лучше 'sub' утверждение) оттуда? Это не потребует дополнительного обращения к серверу Keycloak.