Как keycloak определяет, какой алгоритм подписи использовать? - PullRequest
1 голос
/ 13 июля 2020

Я пишу приложение, которое использует keycloak в качестве службы аутентификации пользователя. У меня есть обычные пользователи, которые входят в Keycloak из внешнего интерфейса (веб-браузеры), и пользователи служб, которые входят в систему из внутреннего интерфейса (PHP в IIS). Однако, когда я вхожу в систему из бэкэнда, keycloak использует HS256 в качестве алгоритма подписи для токена доступа и, таким образом, отклоняет его для дальнейшего взаимодействия, поскольку RS256 установлен в области и в настройках клиента. Чтобы обойти эту проблему, я хотел бы «притвориться внешним интерфейсом», чтобы получить подписанные токены доступа RS256 для моих пользователей службы.

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

В настоящее время я отлаживаю проблему, используя один и тот же идентификатор пользователя / pw / client id / grant как на интерфейсе, так и на сервере, так что это не может быть проблемой .

Пока что я безуспешно пробовал:

  • копирование пользовательского агента
  • копирование каждого отдельного HTTP-заголовка (Host, Accept, Content-Type, User-Agent, Accept-Encoding, Connection, даже Content-Length такие же, как и данные формы)
  • двойная проверка, успешен ли вход в keycloak или нет - это так, просто он использует неправильный алгоритм подписи

Так как же keycloak определяет, с каким алгоритмом подписывать токены? Если он отличается от версии к версии, где я должен искать ответ в коде keycloak?

EDIT: разъяснение потока входа в систему и причин, почему бэкэнд его обрабатывает.

Если пользователь входит в журнал in, вот что происходит:

  1. клиент - [данные для входа] -> сервер keycloak
  2. сервер keycloak - [доступ и обновление sh токена с прямым предоставлением токена ] -> клиент
  3. клиент - [токен доступа] -> сервер приложений
  4. (сервер приложений проверяет токен доступа)
  5. сервер приложений - [данные] - -> client

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

  1. клиент - [запрашивает список пользователей] -> сервер приложений
  2. сервер приложений - [данные для входа в систему пользователя службы] -> сервер keycloak
  3. сервер keycloak - [токен доступа с прямым предоставлением] -> сервер приложений
  4. сервер приложений - [токен доступа] -> сервер keycloak получить конечную точку API списка пользователей
  5. (сервер приложений фильтрует подробные данные пользователей только в список имен пользователей)
  6. сервер приложений - [список пользователей] -> клиент

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

В последнем list, шаг 4 является неудачным, поскольку шаг 3 возвращает подписанный маркер доступа HS256. В предыдущем списке шаг 2 правильно возвращает маркер доступа, подписанный RS256.

1 Ответ

0 голосов
/ 16 июля 2020

Спасибо за разъяснения. Если позволите, я отвечу на ваш вопрос, возможно, иначе, чем ожидалось. Пока вы сосредотачиваетесь на алгоритме подписи токена, я думаю, что в ваших потоках OAuth2 либо есть ошибки в отношении их использования, либо вы столкнулись с некоторым недоразумением. Предоставление доступа", которое относится к потоку OAuth2 Resources Owner Credentials Grant, является либо ложным заявлением, либо ошибкой в ​​вашей архитектуре.

Как указано в собственной документации Keycloak (но также несколько иначе в официальном OAuth.2 ссылки):

Предоставление учетных данных пароля владельца ресурса (Гранты прямого доступа) ... используется клиентами REST, которые хотят получить токен от имени пользователя . Это один HTTP-запрос POST, который содержит учетные данные пользователя, а также идентификатор клиента и секрет клиента (если это конфиденциальный клиент). Учетные данные пользователя отправляются в параметрах формы. HTTP-ответ содержит токены идентификации, доступа и обновления.

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

Мое предложение

Вместо этого в вашем случае для потока (1) я бы увидел Поток кода авторизации ...

  • предполагая, что «Клиент» относится к обычным пользователям в браузере (перенаправлен на аутентификацию Keycloak из вашего фронтального приложения)
  • и предполагая, что вам на самом деле не нужны идентификатор и токены доступа обратно в вашем клиенте, если у вас нет уважительная разумная причина. Поскольку потоки, позволяющие это, считаются устаревшими / устаревшими и больше не рекомендуются. В этом случае мы будем говорить о Implicit FlowPassword Grant поток также сейчас не приветствуется).

Итак, я думаю, что представленный обмен (первая последовательность с пунктами с 1 по 5 в вашем post) некорректно.

Для второго потока (бэкэнд -> список пользователей) я бы предложил две модификации:

  • Разрешить пользователям опрашивать внешнее приложение для получения списка пользователей и, в свою очередь, фронтенд попросит бэкэнд вернуть его. Серверная часть, имеющая служебную учетную запись для клиента с view-roles, сможет получить необходимые данные:

     Client (logged) --> Request list.users to FRONTEND app --> Get list.users from BACKEND app
                                                                   (<--> Keycloak Server)
                     <----------------------------------------- Return data.
    
  • Использовать Предоставление учетных данных клиента (поток) for Backend <> Keycloak для этого варианта использования. В приложении будет service account, которому вы можете назначить определенные c области действия + роли. Он не будет работать от имени какого-либо пользователя (даже если вы можете получить исходный запросчик другим способом!), Но будет выполнять свою работу совершенно безопасно и просто. Вы даже можете определить c Client для этих обменов, которое будет bearer-only.

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

Я что-то пропустил или совершенно не прав ...? Ты мне скажи.

...