OpenID Connect только для аутентификации и мой собственный db для авторизации в архитектуре микросервиса

Dac0d3r спросил: 13 июня 2018 в 09:57 в: oauth-2.0

За последние 10 дней я прочитал просмотренный ВСЕ контент, который я смог найти при понимании OAuth2 и OpenID Connect, только чтобы найти, что многие люди не согласны с реализацией, что меня действительно смущает.

Насколько я понимаю, все статьи и примеры, которые я нашел, предполагают, что вы хотите получить доступ, например. календаря Google, информации профиля или электронной почты, если вы, например. войдите в Google, но мне НЕ нужен доступ, кроме моего собственного API. Я хочу использовать Google, Facebook и т. д. для входа в систему и получения идентификатора, который я могу связать с моим пользователем в моей собственной базе данных, - не более того .

Я попытаюсь проиллюстрировать мой пример использования и использовать его в качестве примера.

Заметка на диаграмме: служба аутентификации, вероятно, может быть встроена в шлюз API - не это важно для этого примера, так как это не о том, "где это сделать", а "как это сделать" лучший способ "для такой архитектуры, как мой, где он используется для моих собственных API / Microservices, а не для доступа к Google, Facebook и т. д. внешний API

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

Самые основные требования для этой архитектуры вы видите здесь:

  • Пользователи можете войти в Google, Facebook и т. Д.
  • Тот же логин будет использоваться для всех микросервисов.
  • Пользователь OpenId будет иметь связанную учетную запись в базе данных
  • Определен пользовательский доступ в моем собственном db на основе групп, ролей и разрешений

Я не намерен использовать внешние API после того, как пользователь будет аутентифицирован и зарегистрирован. Нет необходимости когда-либо получать доступ к календарю пользователей, электронной почте и т. д., поэтому мне действительно нужна часть аутентификации и ничего больше (подтверждение успешного входа в систему). Весь пользовательский доступ определен в моей собственной базе данных.

Поэтому возникает несколько фундаментальных вопросов.

  • Прежде всего, это OpenID Connect, даже правильный инструмент для работы только для проверки подлинности (я не буду использовать для авторизации, поскольку мне не нужен доступ для чтения / записи к API google / facebook, отличный от того, чтобы получить идентификатор от аутентификации)?
  • Люди обычно не согласны с тем, использовать маркер ID или Access для доступа к вашим собственным API. Насколько я понимаю, токен ID предназначен только для клиента (пользовательского агента), а токен доступа - например. доступ к календарю Google, электронной почте и т. д. Внешний API API OpenID ... но поскольку я буду получать доступ только к своим собственным API, мне нужен токен доступа или токен идентификатора - что является правильным способом защиты ваш собственный API?

Если токен идентификатора действительно подходит только клиенту, он может показать, например. в настоящее время вошедший в систему пользователь, не обращаясь к БД, у меня есть 0 для него, так как я, вероятно, запрошу пользователя из db и сохраню его в редуксе для моего реагирования на внешнее приложение.

Дилемма: хранить пользовательские данные, группы, роли и разрешения внутри JWT или не для авторизации API?

  • Сохраняя только идентификатор пользователя в токене, это означает, что я всегда разрешить аутентифицированным пользователям, имеющим действительный токен, вызывать конечные точки перед авторизацией и сначала определять доступ на основе результата запроса db и разрешений в моей собственной базе данных.
  • Сохраняя больше данных о пользователе внутри JWT , это означает, что в некоторых случаях я мог бы выполнить проверку авторизации / доступа (групповой, ролевой, разрешающей) до попадания в API - возможно только с информацией пользователя, группами, ролями и разрешением, хранящимися в JWT, выданном при входе в систему , В некоторых случаях это было бы невозможно из-за, например. разрешения доступа к содержимому CMS находятся на уровне каждого узла. Но все равно это означало бы немного лучшую производительность.

Как вы можете видеть на диаграмме, я отправляю все запросы API через шлюз, который (сам по себе или с помощью службы проверки подлинности) переводит непрозрачный токен доступа в некоторый JWT с идентификатор, поэтому я могу идентифицировать пользователя в базе данных графа, а затем проверить, есть ли у пользователя требуемые группы, роли и разрешения - не от внешнего API, а от моей собственной базы данных, как вы видите на диаграмме.

Это похоже на большую работу над каждым запросом, даже если службы могут совместно использовать JWT в случае, если нескольким службам необходимо перекреститься друг с другом.

Преимущество всегда поискать пользователя, и его разрешения в db, естественно, что в момент изменения уровней доступа пользователей ему немедленно отказывают / предоставляют доступ, и он всегда будет синхронизироваться. Если я храню данные пользователя, группы, роли и разрешения внутри JWT и сохраняю это в локальном хранилище клиента, я предполагаю, что он может представлять проблему безопасности правильно, и было бы довольно сложно обновить информацию пользователя, группы, роли и разрешения внутри этого JWT?

Одним из больших преимуществ хранения уровней доступа пользователей и информации внутри JWT, конечно, является то, что во многих случаях я мог бы заблокировать пользователя от вызова определенных API, вместо того, чтобы определять доступ после поиска db.

Итак, вся вещь перевода маркера означает повышенную безопасность за счет производительности, но, как правило, рекомендуется и стоит того? Или это достаточно безопасно для хранения информации о пользователях и групп, ролей, разрешений внутри JWT?

Если да, я сохраняю всю эту информацию из своего собственного БД в токене идентификатора, токена доступа или третьего токена - какой токен отправлен в API и определяет, должен ли пользователь получать доступ к данному ресурсу на основании его прав доступа в db? Действительно ли мне нужен токен доступа, если мне не нужно взаимодействовать с API-провайдерами ID? Или я сохраняю и добавляю все свои группы, роли, разрешения внутри маркера ID (это не кажется мне чистым), выпущенное подключением OpenID, и вызываю API и авторизую свои собственные конечные точки API, используя это, даже если некоторые говорят, что вы не следует использовать маркер ID для доступа к API? Или я создаю новый JWT для хранения всей информации, полученной из моей базы данных, которая должна использоваться для решения, может ли пользователь получить доступ к данной конечной точке ресурса / API?

Пожалуйста, не просто ссылку на общий спецификации или общую информацию, поскольку я уже прочитал все это - я просто не понял, как применить всю эту информацию к моему фактическому варианту использования (диаграмма выше). Попытайтесь быть максимально конкретными.

Сделала еще одну попытку попробовать и просто поток:


3 ответа

Matt Ke ответил: 17 июня 2018 в 11:03

Я пытаюсь ответить на подзаголовки в том порядке, в котором они были заданы. (Если на один вопрос не был дан ответ, прокомментируйте.)

!!! Следующие ответы применяются к архитектуре, в которой вы используете сторонние IDID OpenID Connect для аутентификации. Они не применяются, если у вас есть собственный IDID OpenID Connect. !!!

1. Возможно, служба аутентификации была встроена в шлюз API?

Да, служба аутентификации может быть встроена в шлюз API. (Например, DataPower от IBM выполняет аутентификацию и действует как шлюз API.) Если у вас будет большая нагрузка на шлюз API, тогда было бы неплохо разделить их. Затем вы можете запустить несколько служб шлюза API (с кешированием).

2. Является ли OpenID Connect даже правильным инструментом для аутентификации?

Да, OpenID Connect определенно является правильным инструментом.

Он позволяет Клиентам проверять личность Конечный пользователь ..., а также для получения базовой информации о профиле конечного пользователя ....

(Многие организации начали использовать / поддерживать OpenID Connect.) 3. Использовать идентификатор или токен доступа (OpenID Connect IDP) для доступа к вашим собственным API?

Я бы не стал повторно использовать идентификатор или токен доступа для доступа к вашим собственным API. Оба токена должны использоваться только при аутентификации. Служба проверки подлинности должна быть авторизационной службой аутентификации и (OAuth2) и должна выдавать собственные токены доступа, которые должны работать только с вашими собственными API.

После этого вы будете иметь два вложенных потока OAuth2. Один из ваших клиентских приложений и службы авторизации, а другой - между службой проверки подлинности и IDID OpenID Connect. (Ваше клиентское приложение не увидит второй поток OAuth2.)

4. Мне даже нужен токен доступа (IDID OpenID Connect)?

Маркер идентификатора может не содержать всю необходимую информацию. (Некоторые претензии являются необязательными, и некоторые IDP не будут предоставлять их в токере ID.) В этом случае вы используете токен доступа для получения информации из конечной точки информации пользователя.

(Вам нужны конкретные области, чтобы получить конкретную информацию из конечной точки информации пользователя.)

5. Является ли токен идентификатора действительно только для клиента?

Нет, маркер ID (также) используется вашей службой аутентификации для аутентификации пользователя.

6. Сохранять пользовательские данные, группы, роли и разрешения внутри JWT?

Использование JWT не только приносит преимущество безопасности, но и повышает производительность. Детали пользователя и т. Д. Должны быть прочитаны только один раз (за запрос) из базы данных и могут использоваться каждой службой. (Вы также можете добавить кеширование к шлюзу API. Например, одна минута старых пользовательских данных может быть приемлемой.)

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

7. Передача JWT на стороне клиента.

Поскольку JWT подписан, проблема безопасности отсутствует. Однако отменить выданные JWT не так просто.

Лучше использовать JWT только после шлюза API и переводить их на шлюз API. (Между клиентом и шлюзом API токен доступа должен быть только случайной строкой.)

8. Я храню и добавляю все свои группы, роли, разрешения внутри маркера ID?

Вы не можете добавлять данные в токен идентификатора. Вам нужно создать новый JWT.

Dac0d3r ответил: 17 июня 2018 в 10:47
3. Вы говорите, что внутри службы аутентификации / шлюза API вы предлагаете сохранить карту в сеансе (redis / memory), сопоставляя самозапускаемый токен (для моих собственных служб / API), который хранится на стороне клиента ( local / sessionStorage) и отправлен в заголовке авторизации как носитель (по каждому входящему запросу в шлюз API), к провайдеру OpenID Connect, предоставленному токеном доступа, который я получил при проверке входа? Итак, серверный сеанс в шлюзе будет похож на {selfIssuedTokenValue:externalOIDProviderAccessTokenFromLogin}?
Dac0d3r ответил: 17 июня 2018 в 10:50
5. Как я понял, цель токена ID заключалась в том, чтобы предоставить самую основную информацию о пользователе клиенту, без дополнительных обращений, чтобы получить дополнительную пользовательскую информацию от внешнего поставщика OIDC. Это не то, что мне нужно - только идентификатор для идентификации пользователя с пользователем в db. Вместо этого я буду приводить информацию пользователя в свой магазин redux при начальной загрузке страницы моего приложения-приложения и не использовать токен для его хранения. Таким образом, идентификатор ID не нужен, теперь, когда мы используем токен доступа и самовыраженный токен для шлюза api для подключения oidc и client к соединению шлюза api?
Matt Ke ответил: 17 июня 2018 в 11:13
3. После успешной аутентификации пользователя вы можете сбросить идентификатор и доступ к токену IDP. Они вам больше не понадобятся.
Matt Ke ответил: 17 июня 2018 в 11:18
5. Это зависит от того, какую претензию вы используете в качестве идентификатора. Некоторые претензии будут указаны в идентификаторе. Тогда вам не понадобится токен доступа. И некоторые претензии могут быть получены только с конечной точки информации пользователя.
Dac0d3r ответил: 18 июня 2018 в 08:33
3: Если я удалю как токен доступа, так и идентификатор, я не смогу идентифицировать пользователя по каждому запросу и посмотреть его в db, если он решит, может ли он получить доступ к конечной точке ресурса / API? Минимальный размер, который мне нужен, - это требование "sub" внутри идентификатора ID? или электронной почты? Или что еще будет использоваться как уникальный идентификатор, который используется для создания связи между пользователем в моей собственной базе данных и аутентифицированным / зарегистрированным пользователем OIDC?
Kavindu Dodanduwa ответил: 16 июня 2018 в 08:40

Это очень длинный вопрос. Но я считаю, что большинство из них можно суммировать, отвечая ниже.

Насколько я понимаю, все статьи и примеры, которые я нашел, предполагают, что вы хотите получить доступ, например. календаря Google, информации профиля или электронной почты, если вы, например. войдите в систему с помощью google,

Вы не обязательно используете токен доступа (идентификатор ID в некоторых случаях) для доступа к услугам, предлагаемым маркером-эмитентом. Вы можете использовать токены по своим API. То, что эти поставщики удостоверений (синоним сервера авторизации или IDP в стенограмме) содержит идентификаторы конечных пользователей. Например, типичный интернет имеет учетную запись Facebook. С помощью OAuth и OpenID Connect один и тот же пользователь получает возможность потреблять ваш API или любую принятую услугу OAuth / OIDC. Это уменьшает создание пользовательских профилей для конечных пользователей.

В корпоративном домене OAuth и OIDC выполняют ту же задачу. Наличие единой учетной записи Azure AD позволяет вам использовать MS Word, а также OIDC AD Azure, для выдачи токенов, которые могут использоваться для авторизации против внутреннего API или стороннего продукта ERP (используемого в организации), который поддерживает аутентификацию на основе OIDC. Надеюсь, теперь ясно.

Примечание на диаграмме состоит в том, что служба аутентификации, вероятно, может быть встроена в шлюз API - не уверен, что это будет лучше?

Если вы планируете внедрить шлюз API, подумайте дважды. Если что-то невелико, и если вы думаете, что можете его поддерживать, тогда идите вперед. Но подумайте о менеджерах API, которые могли бы обеспечить большинство ваших необходимых функций. Я приветствую вас прочитать эту статью о ящике API WSO2 и понять ее возможности (нет, я не работаю для них).

Например, этот менеджер API создал механизм проверки подлинности для OAuth и OIDC. Он может обрабатывать аутентификацию API с помощью простого набора конфигураций. С таким решением вы избавляетесь от требования реализовать все.

Что делать, если вы не можете использовать диспетчер API и должны сделать это самостоятельно

OpenID Connect предназначен для аутентификации. Ваше приложение может проверить токен идентификатора и аутентифицировать конечного пользователя. Чтобы получить доступ к API через API-шлюз, я думаю, вы должны использовать токен доступа.

Чтобы проверить маркер доступа, вы можете использовать конечную точку интроспекции поставщика удостоверений. И чтобы получить информацию о пользователе, вы можете использовать конечную точку пользовательской информации.

После того, как маркер доступа проверен, шлюз API может создать сеанс в течение ограниченного времени (в идеале, чтобы он был меньше или равен времени доступа к токену). Последующие запросы должны прийти с этой сессией для принятия через шлюз API. Кроме того, вы все равно можете использовать проверенный токен доступа. Поскольку вы проверили его при первом вызове, вы можете кэшировать определенный период времени, избегая при этом округлых визитов к проверкам.

Чтобы проверить данные пользователя, разрешения и другие гранты, вы должны завязать привязку пользователя к сеансу или связать пользователя с доступом к токену из шлюза API при проверке токена. Я также не очень понимаю это, так как я понятия не имею, как работает ваша логика БД.

Kavindu Dodanduwa ответил: 17 июня 2018 в 12:27
@ Dac0d3r хорошо, я думаю, вам нужен архитектор решений, чтобы обсудить и полностью понять ваш сценарий. Удачи :)
Dac0d3r ответил: 17 июня 2018 в 08:00
Спасибо за ваш длинный ответ. К сожалению, я не получил разъяснений, на которые я надеялся. Например, все до "Что делать, если вы не можете использовать диспетчер API и должен сделать это самостоятельно" на самом деле не помогло мне ближе к пониманию "как использовать openid-соединение только для проверки подлинности", и если вам нужно только пройти аутентификацию для вашего собственной архитектуры API / микросервисов ". Я не хочу использовать существующий API Manager / Gateway, но строю очень простой, как вы видите на диаграмме. Я постараюсь быть более ясным в своем вопросе, поэтому ответы будут более конкретными. Это слишком абстрактно :-)
Matt Ke ответил: 20 июня 2018 в 04:17

На следующем рисунке показан поток аутентификации OpenID Connect с сторонним IDP (например, Google) для веб-приложения. (Это не относится к архитектуре, в которой вы размещаете свой собственный IDP.)

Я бы не рекомендовал повторно использовать идентификатор или токен доступа из IDP для доступа к вашим собственным API (оба токена должны использоваться только в аутентификация.) Вместо этого вы должны реализовать сервер авторизации OAuth2, который выдает токены доступа для вашего API. (В этом случае у вас есть два потока OAuth2. Один для аутентификации и один для авторизации.)

Вызовы потока аутентификации (авторизация кода) отмечены синим цветом. Запросы потока авторизации (Implicit Grant) отмечены зеленым цветом.

1: Ваша сеть приложение загружается с сервера приложений.

2a: пользователь нажимает кнопку входа в систему, ваше веб-приложение создает URL-адрес авторизации и открывает его. (См. Запрос авторизации)

2b: поскольку пользователь не прошел проверку подлинности и не имеет действительного сеанса с вашим сервером авторизации, URL, который он хочет получить, сохраняется и ваш сервер авторизации отвечает перенаправлением на его Страница входа в систему.

3: страница входа загружается с вашего сервера авторизации.

4a: пользователь нажимает кнопку "Войти с ...".

4b: Ваш сервер авторизации создает URL авторизации IDP и отвечает перенаправлением на него. (См. Запрос на аутентификацию)

5a: URL-адрес авторизации IDP открыт.

5b: поскольку пользователь не прошел аутентификацию и не имеет действительного сеанса с IDP, URL-адрес он хочет получить доступ, и IDP отвечает перенаправлением на свою страницу входа.

6: страница входа загружается из IDP.

7a: пользователь заполняет свои учетные данные и нажимает кнопку входа в систему.

7b: IDP проверяет учетные данные, создает новый сеанс и отвечает перенаправлением на сохраненный URL.

8a: URL-адрес авторизации IDP opend again.

(Шаги утверждения здесь проигнорированы для простоты.)

8b: IDP создает авторизацию и отвечает перенаправлением на URL-адрес обратного вызова вашего сервера авторизации. (См. Ответ на аутентификацию)

9a: Открыт URL-адрес обратного вызова.

9b: Ваш сервер авторизации извлекает код авторизации из URL-адреса обратного вызова.

10a : Ваш сервер авторизации вызывает конечную точку маркера IDP, получает идентификатор и токен доступа и проверяет данные в токере ID. (См.: Запрос токена)

(10b: ваш сервер авторизации вызывает конечную точку информации пользователя IDP, если некоторые необходимые утверждения недоступны в токене идентификатора.)

11a / b: Ваш сервер авторизации запрашивает / создает пользователя в вашей службе / БД, создает новый сеанс и отвечает перенаправлением на сохраненный URL.

12a: URL-адрес авторизации снова открывается.

(Шаги утверждения здесь проигнорированы для простоты.)

12b / + 13a / b: Ваш сервер авторизации создает / получает авторизацию (создает токен доступа) и отвечает перенаправлением на URL-адрес обратного вызова вашего веб-приложение. (См. Ответ на токен доступа).

14a: Откроется URL-адрес обратного вызова.

14b: ваше веб-приложение извлекает токен доступа из URL-адреса обратного вызова.

15: ваше веб-приложение выполняет вызов API.

16/17/18: шлюз API проверяет токен доступа, обменивает токен доступа с токеном JWT (который содержит информацию о пользователях, ...) и переадресация вызова.

Дополнительное видео по вопросу: OpenID Connect только для аутентификации и мой собственный db для авторизации в архитектуре микросервиса

Александр Семёнов "Аутентификация OAuth / OpenID Connect в Enterprise и среда Open API"

OAuth and OpenID Connect for Microservices

Lunch and Learn: Authentication Using OpenID Connect and OAuth2