Как реализовать OpenID Connect с несколькими провайдерами в Django?
Я пытаюсь реализовать несколько SSO (OpenID Connect) логинов в моем приложении, помимо обычного.
Текущие запросы провайдеров - Azure и Okta, но их будет больше. Для каждого крупного клиента, использующего мое приложение, я хочу иметь возможность предоставить ему пользовательский SSO логин, который он может настроить в панели администратора.
Все библиотеки, которые я пытался использовать для этого, либо используют settings.py и локальную аутентификацию django, либо они устарели.
Поток выглядит следующим образом:
Пользователь выбирает свою компанию и кнопку входа SSO -> Получает перенаправление на вход -> Я отправляю id клиента, секрет и т.д. (которые он ввел в панели администратора при регистрации sso соединения) -> В ответ я получаю токен с именем и email пользователя -> С помощью этой информации (email) я нахожу уже существующего пользователя в моей локальной базе данных и регистрирую его в системе -
Ваши собственные приложения обычно предпочитают доверять только одному провайдеру, а когда вы хотите задействовать несколько провайдеров, лучший способ - добавить свой собственный OIDC-провайдер локально, которому доверяют ваши приложения и API. А затем ваш OIDC-провайдер может доверять различным другим провайдерам. Как показано на рисунке ниже:
Если у вас SAAS-приложение, вы можете использовать workos.com для добавления SSO в ваше приложение вместо того, чтобы создавать его самостоятельно. Он поддерживает OIDC, SAML и многие другие провайдеры из коробки, а также имеет SDK для python
https://workos.com/docs/sso/guide/integrate-with-app/install-the-sdk-of-your-choice
-
Пользователь выбирает свою компанию и кнопку входа SSO
OK, вы можете просто разместить кнопки на своем сайте.
-
Получает перенаправление на вход в систему
Вы можете имплантировать /redirect
конечную точку и обязательно сделать что-то для подготовки к получению информации о пользователе от провайдера OAuth2.
-
Я отправляю идентификатор клиента, секрет и т.д. (которые они ввели в панели администратора при регистрации sso соединения)
Это также продолжение шага 2. но я не знаю, как подключиться к панели администратора Django. извините.
-
В ответ я получаю токен с именем и электронной почтой пользователя
Используйте API информации о пользователе провайдера OAuth2. Таким образом, вы можете получить информацию о пользователе в том объеме, в котором вы хотите, если он ее предоставит.
-
с этой информацией (email) я нахожу уже существующего пользователя в моей локальной базе данных и регистрирую его
.
Просто напишите функцию с базой данных. это не сложно.
Думаю, этого достаточно для реализации.
но that they can setup in the admin panel.
Я не уверен, что вы можете настроить "уже сделанную" админ-панель Django. Это может быть трудно сделать.
У меня была похожая проблема, за исключением того, что мне нужна была поддержка нескольких поставщиков идентификационных данных для SAML, а также OIDC, и я решил ее следующим образом.
Я заметил, что реализация SAML SSO пакета django-social-auth поддерживает несколько "idp", основываясь на конфигурации в settings.py.
Исходя из этого, первым шагом было создание абстракции в модели Django, которую я назвал
IdentityProvider
(упуская терминологические различия между SAML и OIDC), и чистого аналога на языке Python под названиемIdp
, который является тонкой оберткой вокруг saml.SAMLIdentityProvider. Итак, в models.py:class IdentityProvider(models.Model): """ SAML or OIDC Identity Provider for SSO. Based on the model exposed by PSA/python3-saml to multiple db-defined SSO setups. """ ... real_backend = models.CharField("See below for what this is!!!!")
и в других местах:
class IdP(saml.SAMLIdentityProvider): def get_display_name(self, lang): ... return display_name def get_logo(self): ... return logo
Бэкенд SAML был дополнен
MultiBackendMixin
, чтобы позволить обнаруживать idps либо из конфигурации в settings.py, либо вIdentityProvider
экземплярах:class SAMLSandboxAuth(MultiBackendMixin, saml.SAMLAuth): ...
и аналогичный для OIDC:
class OIDCSandboxAuth(MultiBackendMixin, base.BaseAuth): ...content based loosely on saml.SAMLAuth...
Концептуально, все SSO выполняется через эти "SandboxAuths", и каждый из них отсылает к "реальному" бэкенду для фактической логики:
class SAMLAuth(saml.SAMLAuth):
...generic SAML backend...
class SAMLAuthMicrosoftAzureAD(SAMLAuth):
...Microsoft Azure AD SAML hacks for login_hint...
Обратите внимание, что я эффективно использовал saml.SAMLAuth
один раз как SandboxAuth, и один раз как "настоящий" бэкенд!!! Случай с OIDC аналогичен, за исключением того, что, конечно, OIDCSandboxAuth
полностью принадлежит мне, как указано выше.
Я должен отметить, что мой поток такой же, как и ваш, ИСКЛЮЧАЯ то, что на первом этапе пользователь должен указать свое имя входа. Я использую его для поиска IdentityProvider
(и, следовательно, отображения имени и логотипа), который он должен использовать. "Настоящие" бэкенды предоставляют это имя как login_hint, если другой конец поддерживает его.