Способы объединенной аутентификации на ряде сайтов. Нужно что-то вроде распределенного OpenID
Дано: несколько веб-приложений. Это просто несколько копий одного приложения, которые запущены на разных поддоменах. Например: s1.myapp.com, s2.myapp.com, s3.myapp.com. Приложения между собой никак не связаны, т.е. запущены на разных физических серверах и у каждого своя база данных.
Авторизация на всех этих доменах одинаковая — по логину/паролю.
Задача: создать сайт вида help.myapp.com, который бы был доступен только юзерам, авторизованным на любом из приложений.
Мне пришли в голову следующие идеи:
1. Создание единого узла аутентификации (auth.myapp.com) и использование OpenID для аутентификации на help.myapp.com.
Минус: дополнительная работа по изменению архитектуры.
2. Ввод пароля непосредственно на help.myapp.com и запросы ко всем имеющимся базам данных с проверкой, есть ли хотя бы на одном из них такое сочетания логина/пароля.
Минусы: решение выглядит коряво. К тому же, пользователям прийдется вводить логин/пароль как на основном сайте их приложения, так и на сайте help'а.
3. Авторизация по referrer'у. То есть, если человек пришел по ссылке хотя бы с одного из допустимых сайтов, он автоматически получает доступ, а также, куки, запоминающие его как авторизованного.
Минусы: referrer можно очень просто подделать. К тому же, не будут работать прямые ссылки на странички help'а, если юзер не авторизован. Например, если кому-то прислали ссылку на help через скайп, человеку прийдется сначала переходить в help с его основного сайта, чтобы пройти аутентификацию, а потом уже открывать ссылку.
Есть ли другие способы? Можно ли что-то улучшить в приведенных выше?
Заранее спасибо.
Допустим сейчас приложение ставит у Вас печеньку на домен s1.myapp.com с именем login.
В новой редакции пусть оно так же ставит печеньку на домен .myapp.com с именем s1_login.
Тогда на help.myapp.com у Вас будет доступна эта «новая печенька», а по префиксу Вы поймете кто ее поставил и в какую базу ломиться за проверкой.
О господи, под печенькой вы имели в виду куку? :) Извините, сразу не понял.
Я не знал, что можно получать доступ к одной куке с разных доменов (даже если они поддомены одного доменного имени). Спасибо, сейчас об этом почитаю.
Да, как раз это и нужно. Хммм, тогда можно:
1. Ставить куку вида *.myapp.com навечно и записывать в неё адрес сервера как значение куки;
2. На каждом из серверов s*.myapp.com поднять OpenID-провайдер;
3. При попытке зайти на help.myapp.com, перенаправлять на соответствующий сайт и проверять аутентификацию через OpenID.
Похоже, так будет работать :) Спасибо!
P.S. Но если у кого-то будут еще другие предложения, буду рад услышать.
У CAS другое предназначение. Его обычно используют, если нужно из разнородных клиентов аутентифицироваться на одном сервере.
В то же время, OpenID предназначен для того, чтобы с помощью аутентификации на одном провайдере можно было логиниться в любых сторонних приложениях.
Даже если CAS и можно применить в моем случае, я не вижу, чем он лучше OpenID. Поясните?
С удовольствием.
Для схемы с OpenID пользователь будет аутентифицироваться на auth.myapp.com, и для каждого s*.myapp.com на который он будет заходить, он будет подтверждать вход по OpenID.
Для схемы с CAS пользователь будет будет аутентифицироваться на auth.myapp.com, но только по редиректу с первого из s*.myapp.com на который он зайдёт.
С точки зрения пользователя математика проста. OpenID — это не Single Sign On.
Вцелом схема с OpenID тоже рабочая, но смысла в ней особого не вижу.
Да, кстати, CAS используется именно для аутентификации на разных серверах (с использованием центрального аутентифицирующего сервиса — CAS).
Для аутентификации разнородных клиентов на одном сервере HTTP предоставляет достаточный уровень абстракции.
Ага, кажется, начинаю понимать. Но есть один нюанс. Пользователь никогда не зайдет на какой-либо s*.myapp.com, кроме своего, на котором он, собственно, и зарегистрирован. Суть задачи — в том, чтобы, имея разрозненные сервера, предоставлять всем их пользователям доступ к одному help.myapp.com.
Спасибо, что разъяснили про CAS, буду обдумывать :)
Может в момент авторизации на любом из сайтов, паралельно его авторизовать на сайте auth.myapp.com? И тогда при заходе на help.myapp.com его перекидываем на auth.myapp.com и если он там уже авторизован, то авторизовываем и на help.myapp.com, а если еще не авторизован, то показываем поле логина и пароля. И когда пользователь вводит данные, совпадение логина с паролем ищем по базам всех сайтов.
Я думал и о чем-то вроде этого. Но ведь тогда прийдется при авторизации на s*.myapp.com перенаправлять юзера на auth, чтобы записать в браузер авторизационную куку, а потом обратно. Или без этого можно как-то обойтись?
как вариант:
На одном из сайтов (или на отдельном) устраиваете центр аутентификации. На всех страницах сайтов, если клиент еще не авторизован на сайте, запрашиваете яваскрипт из этого «центра».
Если клиент не авторизован в «центре» — сервер возвращает пустой файл, а если авторизован, то некоторый код, который распространяет авторизацию и на «дочерний» сайт (выставляет куки, редиректит, или что-либо еще).
Естественно не стоит забывать о безопасности, стоит ввести токены или что-либо еще.
Если все сайты — поддомены одного домена, то можно проставить общую куку.
Если сильно менять архитектуру слишком затратно, то можно разово собрать учетки со всех сайтов в единую базу (хотя бы потому, что так быстрее искать), и при добавлении новых пользователей отправлять копию на основной сервер (или синхронизировать базы, как вам удобнее).
1. Организуйте простую шутрую БД, в которую будете кидать ключ-логин-приложение и хранить закрытый ключ (код сессии например)
2. Открытый ключ на основе общего алгоритма (хеширование, соль, еще один закрытый ключ) отсылаете кукой клиенту)
В результате знаете уровень авторизации, откуда пришел в последний раз, что делал юзер или приложение. Каждое приложение автономно может работать со своим ключом в бд авторизации, так и править общий закрытый ключ. Можно SQL(MyISAM, Memory в MySQL), можно noSQL (memcache, redis, cassandra). Главное, что никто никому не завязывает руки.
сделайте провайдер openID, который автоматически авторизует ваши сайты… рано или поздно вы захотите еще один сайт прикрутить, а потом еще один сайт и т.д. Единая авторизация избавит вас в дальнейшем от многих проблем. И да — для пользователей еще один сервис «OpenID» будет только плюсом :-)