Я создаю приложение поставщика услуг, в котором пользователи должны иметь возможность делиться своими данными со сторонним приложением, используя OAuth2 и OpenID Connect.
Стандартный поток согласия OAuth2 авторизует области действия (какие атрибуты/роли для совместного использования). Однако, поскольку атрибуты могут состоять из нескольких значений, мы также хотели бы позволить пользователю выбирать, какие значения использовать.
Итак, мой вопрос: следует ли заменить весь поток согласия OAuth2 пользовательским, в котором области действия OAuth2 более или менее заменены явными парами ключ/значение атрибута? Немного странно удалять такой ключевой компонент OAuth2, как области действия, что вы думаете? Любые другие предложения?
В настоящее время я испытываю сервер авторизации Spring для настройки потока согласия (поскольку Keycloak, который мы сейчас используем, не кажется таким гибким с логикой согласия).
Я думаю, что замена стандартного потока согласия на сервере авторизации spring потребует перезаписи как OAuth2AuthorizationConsentService, OAuth2AuthorizationConsentAuthenticationProvider, так и всех классов OAuth2...AuthenticationProvider, которые используются для аутентификации, чтобы перенаправить согласие на новый поток согласия.
То, что вы описываете, является точной целью области: содержать согласие пользователя на то, к каким данным (именам атрибутов) конкретный клиент может получить доступ от своего имени. Обычно, чтобы упростить выбор пользователя и обслуживание программного обеспечения, степень детализации атрибутов при выборе области не совпадает с внутренней моделью данных (например, область contact
может представлять столбцы телефона, страны, города, почтового индекса и улицы в базе данных).
Поскольку роли, группы, разрешения или что-то еще, что должно быть сопоставлено с полномочиями Spring, не указано ни Oauth2, ни OpenID, серверы авторизации используют частные утверждения для хранения этих данных (и обычно не области). Если вы привыкли к Keycloak, то должны были заметить, что роли по умолчанию помещаются в realm_access.roles
и resource_access.{client-id}.roles
. Другие серверы авторизации будут использовать другие частные претензии.
Проще говоря, роли (или группы, или разрешения, или как бы вы это ни называли) определяют, что конкретный пользователь может делать в системе, когда область должна содержать, к каким ресурсам конкретному клиенту разрешен доступ от имени этого пользователя.
Таким образом, мы не хотели бы делиться доступом к самому атрибуту, мы в основном хотели бы создать новый профиль пользователя, настроенный для каждой третьей стороны.
В OAuth2 пользователи не входят в стороннюю систему. Они входят в систему на сервере авторизации и предоставляют области действия каждому клиенту (возможно, стороннему приложению), чтобы позволить ему манипулировать ресурсами на серверах ресурсов. В вашем случае ресурс-сервер также является сервером авторизации, а ресурс — содержимым идентификатора токена. Просто попросите сервер авторизации просмотреть область действия перед выдачей идентификатора-токена, как это должен делать любой ресурсный сервер, когда пользователь может ограничить данные для каждого клиента.
Хорошо, но как пользователю указать, какой адрес электронной почты использовать в потоке согласия в качестве области действия, если область действия — это просто строка, а не значение ключа? Ресурсом в нашем случае, вероятно, будет сервер ресурсов сторонних приложений. Скорее всего, они будут иметь свой собственный сервер авторизации и использовать наш сервер авторизации в качестве поставщика услуг. Таким образом, пользователи в основном хранятся на нашей стороне, а затем, когда они входят на свой сервер авторизации, им необходимо войти в наше приложение и поделиться данными, которые они хотят, со сторонним сервером авторизации.
Таким образом, их сервер авторизации также будет содержать пользователя, который содержит подмножество данных пользователя в нашей системе.
@user3677636 user3677636 Если у каждого приложения есть собственный сервер авторизации, вам не нужен собственный. Я не вижу никакой причины. Если вы хотите использовать централизованный каталог пользователей, вы можете использовать LDAP, Active Directory, ... Там вы можете настроить, какая система может видеть любой адрес электронной почты.
Хм, хорошо.. Но мы по-прежнему хотим, чтобы они использовали наш метод аутентификации каждый раз, когда они входят в систему. Таким образом, каждый раз, когда они входят в стороннее приложение, они используют наш метод входа (PKI с коэффициентом 2) и могут обновлять значения.
Означает ли это, что нам нужен собственный сервер авторизации?
Мой босс — провидец, и он не технарь, но он делал это раньше и пытается объяснить технические детали, которые он не полностью понимает, поэтому иногда это немного сбивает меня с толку.
Я думаю, я мог бы создать свой собственный поток согласия, который использует области, как обычно, а также создает нового пользователя, привязанного к этому клиенту, и когда они принимают согласие, они также обновляют своего клиента-пользователя. Затем id-токен генерируется на основе областей действия и атрибутов клиент-пользователь?
Вам просто нужно открыть конечную точку с информацией о пользователе на собственном сервере ресурсов и пользовательский интерфейс (клиент «администратор»), чтобы контролировать то, что отображается для каждого клиента. [Openid определяет только один адрес электронной почты](openid.net/specs/openid-connect-core-1_0.html#Standard Claims). Если вы определяете максимальное количество писем в своей системе, вы можете решить свою проблему с помощью областей видимости (email
, alt_email1
, alt_email2
и т. д.), иначе вам придется реализовать собственную логику, чтобы квадраты помещались в круглые отверстия (карта нестандартная данные для требований OpenID)
Если вы хотите настроить как информацию о пользователе, так и токен идентификатора в Keycloak, вы можете использовать «сопоставитель», но вам, возможно, придется связать Keycloak со своей собственной базой данных пользователей, чтобы иметь несколько электронных писем... образец сопоставления. Он добавляет частное утверждение, но также может изменить стандартное утверждение)
@ ch4mp хм, хорошо .. Я имею в виду не только стандартные утверждения openid, мы хотим иметь возможность таким образом делиться любым атрибутом.
«любые другие атрибуты» являются частными утверждениями OpenID.
Конечная цель состоит в том, чтобы у пользователя была возможность иметь несколько электронных писем (или других атрибутов), а во время потока согласия он должен был иметь возможность выбрать, какое электронное письмо будет передано третьей стороне.
Давайте продолжим обсуждение в чате.
Думаю, я бы добавил некоторые примечания, основанные на прецедентах, о вовлеченных сторонах и о том, как должно работать согласие.
КЛИЕНТ
Клиентское приложение просто перенаправляет с параметром области. Можно отправить параметр претензии, но он редко используется. Область может быть profile
и состоять из утверждений name
и date of birth
.
СЕРВЕР АВТОРИЗАЦИИ
Это представляет запрошенную информацию на экране согласия. Самый гибкий способ сделать это — представить претензии, например, в виде флажков. Некоторые утверждения, например имя, могут быть помечены как обязательные и использовать отключенный флажок. Другие, например дата рождения, могут быть необязательными. Пользователь может отменить выбор последнего утверждения, и тогда оно не будет включено в выпущенные токены.
НАСТРОЙКА СОГЛАСИЯ
В идеале для достижения вышеперечисленного не требуется никаких настроек, которые должны работать из коробки. Однако это может быть не так для Spring. Однако можно настроить согласие. Интересный случай, когда это делается в Open Banking, где пользователь может согласиться на выплату суммы денег во время выполнения:
I consent to pay company X £100 for product Y from account Z
Ознакомьтесь с образцом официального индивидуального согласия! В этом примере демонстрируется пользовательский экран согласия без замены встроенных компонентов для обработки отправки экрана согласия и сохранения согласия пользователя в файле OAuth2AuthorizationConsentService
.
В частности, эти строки настраивают страницу согласия, а эта конечная точка контроллера реализует логику построения пользовательского экрана согласия, который может быть всем, что вам нужно для вашего приложения.
Если вы хотите настроить то, что сопоставляется с экрана согласия с сохраненной авторизацией, вы должны настроить конечную точку авторизации OAuth2 с помощью authorizationRequestConverter()
. Области просто хранятся как «авторитеты», поэтому вы можете вместо этого (или в дополнение) хранить все, что хотите.
Чтобы настроить токен доступа (JWT), созданный в результате этого согласия и авторизации, укажите OAuth2TokenCustomizer<JwtEncodingContext>
, как в примере OAuth2TokenCustomizer из справочной документации.
Как приложение узнает, какой путь перенаправить после того, как пользователь прошел через экран согласия?
@Holm redirect_uri
из запроса на авторизацию используется для перенаправления обратно клиенту с параметром code
(код авторизации).
Хм, я не уверен, что понимаю. На самом деле, мы хотели бы контролировать в основном значения id-token oidc. Пользователь должен, например. иметь возможность иметь несколько адресов электронной почты в нашей системе, но когда они входят в стороннюю систему с помощью нашего поставщика услуг, они должны иметь возможность выбрать 1 адрес электронной почты, чтобы поделиться с этой конкретной третьей стороной, а также поделиться другим адресом электронной почты с другой третьей стороной.