Как организовать сложную авторизацию с openid connect?
Добрый день, коллеги! Появилась у меня задача, но всё не могу понять, как правильно её решить.
Вводные: есть партнёр, с которым происходит синхронизация пользователей. Читай - они нам передают ID, email и имя иногда. В их системе работают пользователи, которые авторизуются по OpenID Connect.
Также есть наша система, в которой эти пользователи должны делать какие-то действия, которые мы должны сохранять и привязывать к ID пользователей. Мы настраиваем авторизацию по OpenID Connect, пересылаем пользователя к ним (там он, допустим, уже авторизован). Пользователь прилетает к нам, мы имеем его Access Token, Refresh Token, ID и прочий фарш. Но у нас также есть свой сервер авторизации (тоже OpenID Connect), где пользователь также должен авторизоваться.
Получается, нам необходимо настроить такую связку: пользователь авторизуется у них => прилетает к нам, передавая его ID => авторизуется у нас сразу по этому ID.
Итого вопрос: как реализовать этот последний пункт грамотно? То есть, можно пойти в обход OpenID, который работает у нас и врубать авторизацию только по этому ID от партнёра, но это как-то не безопасно что-ли. Есть ли какие-то механизмы, которые позволяют объединить 2 OpenID Connect сервера без затрагивания сервера партнёра?
Вы получаете вот весь этот фарш - access token, refresh token, id token (у вас же OIDC). Сохраняете это в системе, из ID токена вы берете данные пользователя, создаете в своей системе (если не было такого ранее) и автоматически его логините на срок жизни токена. В каждой вашей системе отдельно. Так работает SSO. Второй OpenID сервер вам для этой операции не нужен. В крайнем случае вы можете использовать Federation
Александр Вульф
@mannaro Автор вопроса, куратор тега JavaScript
Да, не нужен. Но у нас база пользователей своя, плюс мы туда добавляем пользователей из системы партнёра, поэтому избавиться от собсвенного OpenID сервера не получится - надо как-то авторизовывать наших пользователей наравне с пользователями партнера :)
Александр Вульф, тогда мне интересно зачем вам система партнера?) Но вообще, технически, вы можете сделать Federated Identity. Обычно его не так используют, но это вполне возможно. В любом случае добавлять себе пользователей из стороннего UsersPool это не очень хорошо.
Для примера. Допустим у вас есть Auth0 + Active Ditectory и VK. Вы же не будете себе новых пользователей в VK в свой домен добавлять? не будете
Написано
Александр Вульф
@mannaro Автор вопроса, куратор тега JavaScript
Иван Шумов, система партнера нужна для того, что мы не знаем логин/пароль пользователя. А пользователь их знает и вводить на нашем сайте не должен (как минимум потому, что мы не сможем их проверить). Поэтому и нужен сервер партнера, где он уже авторизован или введёт данные, которые они смогут проверить.
Александр Вульф, тогда вам разумно завязаться на OIDC партнера и подключить свой user-pool к ним как опциональный. Иначе вы таких багов потом словите - не оберешься разгребать
Написано
Александр Вульф
@mannaro Автор вопроса, куратор тега JavaScript
Иван Шумов, не совсем понял, что имеешь в виду. Можешь, пожалуйста, пояснить?
Пока есть ещё мысль такая: пользователь у нас на клиенте нажимает кнопку, попадает к нам на сервер авторизации, откуда ждет токен. Наш сервер авторизации вместо запроса логина/пароля пересылает пользователя на сервер партнера, где тот авторизуется и возвращается обратно к нам на сервер авторизации. Там мы уже имеем ID пользователя, выпускаем свой токен на время жизни токена партнера и высылаем их на клиент. А дальше работаем как со своим пользователем. Но пока не могу понять, насколько жизнеспособна данная схема.
Написано
Александр Вульф
@mannaro Автор вопроса, куратор тега JavaScript
Иван Шумов, проблема в том, что мы не можем вообще никак влиять на их сервер OpenID. От слова вообще. И они ничего не знают о наших пользователях.
Александр Вульф, тут один из вариантов - либо у вас должна быть возможность залогиниться через партнера, либо наоборот. То есть один из вас подключает другого как способ аутентификации. И да, не забываем что OpenID, в принципе, как и Oauth2 - delegation протокол. То есть логинит он где-то там, а отдельному сервису позволяет выполнять действия от своего имени (грубо, но все-же). Поэтому то что вы хотите сделать звучит как натуральная дичь
Написано
Александр Вульф
@mannaro Автор вопроса, куратор тега JavaScript
Иван Шумов, может быть, я неверно объяснил. Всё что нам нужно - это вместо запроса логина/пароля на своем сервере авторизации (если пользователь не авторизован) как-то понять, что пользователь на самом деле есть. И для этого надо дёрнуть сервер партнёра, который нам скажет, кто именно к нам пришёл.
Что там происходит у них - нам не важно. У нас, считай, своя база и свои пользователи. Ничего от их имени нам делать не надо.
Александр Вульф, дело в том что вам сторонний сервер ничего не может сказать. Пользователь после аутентификации данные в куки их сервера получает и до них вы не дотянетесь. Редирект вы не сможете, по вам вы ничего не получите. Вы изначально поставили задачу как не решаемую
Написано
Александр Вульф
@mannaro Автор вопроса, куратор тега JavaScript
Иван Шумов, почему же не может? Если наш auth сервер выступает как клиент авторизации OIDC, то вполне себе может? Или я чего-то не понимаю?
Александр Вульф, OIDC не про авторизацию. И даже не про аутентификацию. Если вы хотите чтобы в вашу систему зашел пользователь то у него должен быть выбор из систем, которые его аутентифицируют. Его перебрасывает в выбранную систему, там человек заходит, а вам возвращается его токен и базовая информация о пользователе. Дальше вы делаете с этой информацией что хотите.
Тут начинается самое интересное - про ваших партнеров мы тут не знаем ничего. Я предполагаю что у них есть свои системы, которые позволяют заходить через OIDC к ним. Таким образом они - клиент OIDC. И чтобы вам с ними работать вам нужно чтобы они были сервером OIDC. И вам нужно чтобы пользователи заходили к вам через них при возможности.
Есть вариант когда вы можете проводить аутентификацию сервер-сервер, но для этого надо чтобы у партнера было вполне специфическое api. Есть ли оно у них я не знаю