Поток единого входа с использованием JWT для междоменной аутентификации
В интернете много информации об использовании JWT (Json Web Token
) для аутентификации. Но я до сих пор не нашел четкого объяснения того, каким должен быть поток при использовании токенов JWT для решения с единым входом в среде с несколькими доменами.
Я работаю в компании, у которой много сайтов на разных хостах. Давайте использовать example1.com и example2.com. Нам нужно решение с единым входом, которое означает, что если пользователь проходит аутентификацию на example1.com, мы хотим, чтобы он также проходил аутентификацию на example2.com, автоматически.
Используя поток OpenId Connect, я понимаю, что пользователь, который хочет пройти аутентификацию на example1.com, сначала будет перенаправлен на сервер аутентификации (или OP
: "Поставщик OpenId"). Пользователь аутентифицируется на этом сервере, который затем перенаправляет его обратно на исходный сайт example1.com с подписанным токеном JWT. (Я понимаю, что есть другой поток, который возвращает промежуточный токен, который впоследствии можно обменять на настоящий токен JWT, но я не думаю, что это требуется для нас)...
Теперь пользователь вернулся на example1.com и прошел аутентификацию! Он может делать запросы, передавая токен JWT в Authentication
заголовок и сервер могут проверить подписанный JWT и, следовательно, могут идентифицировать пользователя. Ницца!
Первый вопрос:
Как хранить токен JWT на клиенте? Опять же, есть много информации об этом, и люди, похоже, согласны с тем, что использование Web Storage
это путь, а не старый добрый cookies
, Мы хотим, чтобы JWT был постоянным между перезапусками браузера, поэтому давайте использовать Local Storage
не Session Storage
...
Теперь пользователь может перезапустить свой браузер, и он все еще будет аутентифицирован на example1.com, пока токен JWT не истек!
Кроме того, если example1.com нужно сделать запрос Ajax на другой из наших доменов, я понимаю, что настройка CORS позволит это сделать. Но наш основной вариант использования - это не междоменные запросы, а решение с единым входом!
Поэтому главный вопрос:
Теперь, каким должен быть поток, если пользователь заходит на example2.com, и мы хотим, чтобы он прошел аутентификацию, используя токен JWT, который у него уже есть? Local Storage
похоже, не разрешает междоменный доступ, поэтому в данный момент браузер не может прочитать токен JWT, чтобы отправлять запросы на example2.com!
Должен:
- Пользователь снова будет перенаправлен на сервер аутентификации? Когда пользователь аутентифицировался для example1.com, сервер аутентификации мог установить cookie для пользователя, чтобы этот новый запрос аутентификации для example2.com мог использовать этот cookie для проверки того, что пользователь уже аутентифицирован и немедленно перенаправляет его обратно на example2.com. с тем же токеном JWT?
- Или браузер на example2.com может получить доступ к токену JWT, не обращаясь к серверу аутентификации снова? Я вижу, что есть решения для хранения данных, но широко ли они используются? Являются ли они предлагаемым решением для междоменной среды единого входа?
Мы не хотим ничего особенного, мы будем рады наиболее часто используемому решению!
3 ответа
Пользователь должен быть снова перенаправлен на сервер аутентификации и получить новый токен (JWT), который специально предназначен для example2.com. Вот как работает OpenID Connect и любой другой междоменный федеративный протокол SSO.
Перенаправление пользователя в центральную службу аутентификации, когда пользователь не авторизован для запроса учетных данных и выдачи нового токена аутентификации, является распространенным сценарием в системах единого входа, использующих известные протоколы, такие как oauth2 или OpenIdConnect.
Однако, когда эта схема используется среди междоменных доменов, основным недостатком является то, что пользователь будет проходить аутентификацию каждый раз, когда он будет переходить в другой домен из-за политики одного и того же источника: маркер сеанса не может быть разделен между доменами, поэтому SSO будет обрабатывать Пользователь не аутентифицирован.
example2.com
не может получить доступ к данным example1.com
но существует метод обмена данными между доменами с использованием браузера localStorage/cookies и фрейма iframe, указывающего на промежуточный домен sso.example.com
Аутентифицировать пользователя в
example1.com
, перенаправьте его на сервер аутентификации вsso.example.com
после проверки подлинности выполните JWT и сохраните его в localStorage этого домена. После этого перенаправьте пользователя в исходный домен example1.com.Создать фрейм в
example2.com
указывая наsso.example.com
, Iframe в sso.example.com читает токен JWT и отправляет сообщение на родительскую страницуРодительская страница получает сообщение и получает прикрепленный токен, продолжая поток SSO
Нет проблем с политикой того же происхождения, потому что sso.example.com
имеет доступ к своему localStorage, и связь между iframe и родительской страницей разрешена, если источник и место назначения узнают друг друга (см. http://blog.teamtreehouse.com/cross-domain-messaging-with-postmessage)
Чтобы упростить разработку, мы недавно выпустили междоменный SSO с JWT по адресу https://github.com/Aralink/ssojwt
Этот метод идеально совместим с потоками SSO. Это просто способ поделиться маркером аутентификации без перенаправлений и избежать ненужных входов в систему, когда домены объединены
Не уверен, что это ответит на ваш вопрос, но если ваша основная цель - единый вход, я думаю, что простой обратный прокси-сервер решит вашу проблему (по крайней мере, междоменную систему хранения).
Итак example1.com example2.com
станет чем-то вроде
example.com/example1
example.com/example2
(А со стороны пользователя это обычно чище)
Если это не вариант, вам может потребоваться настроить так, чтобы при аутентификации пользователя в 1 домене он использовал AJAX/ скрытые фреймы для создания аутентификации и в других доменах (отправка токена 1 раз по URL, если необходимо).
и если ЭТО не вариант, вам, возможно, придется прибегнуть к имени пользователя + пин-коду, поскольку браузеры ужесточают взаимодействие между доменами.