Глобальная авторизация в веб-системах
…или как реализовать простой Single Sign-on в веб-системах.
Ниже описан простейший протокол, который даёт возможность нам сказать внешней системе, кто к нам вошёл, так, что внешняя система знает, что это говорим ей именно мы, а мы знаем, что мы говорим это именно ей.
- (П) Пользователь.
- (С1) Система 1 — клиент глобальной авторизации. В неё пришёл пользователь без авторизации.
- (С2) Система 2 — сервер глобальной авторизации. В ней пользователь уже авторизован, скорее всего, через cookie.
шаг | кто | что делает | кому |
---|---|---|---|
(П) → | (переходит по ссылке) → | C1 с любыми параметрами. ⇒ C1 хочет перенять авторизацию у С2. | |
1 | C1 → | (делает GET-запрос напрямую) → | С2 с параметрами ga_id=ID&ga_key=KEY ⇒ С2 запоминает соответствие ID и KEY. |
2 | С1 → | (перенаправление браузера пользователя) → | С2 с параметрами ga_id=ID&ga_url=URL&ga_check=CHECK
⇒ С2 даётся возможность прочитать cookie пользователя и получить данные о нём. |
3 | С2 → | (делает POST-запрос напрямую) → | С1 с параметрами ga_client=1&ga_id=ID&ga_key=KEY&ga_data=DATA&ga_nologin=NOLOGIN
⇒ С1 запоминает соответствие ID и переданных данных. |
4 | С2 → | (перенаправление браузера пользователя) → | С1 с параметрами ga_client=1&ga_id=ID&ga_res=CODE
⇒ С1 может взять сохранённые в предыдущем пункте данные и на их основе авторизовать пользователя. |
И ID и ключ являются «секретными», но ID знают и сервера, и пользователь (ID передаётся в браузер), а ключ — только сами сервера. За счёт этого достигается безопасность: пользователь не может сам передать произвольные данные авторизации на сервер, не зная ключа.
Для дополнительной защиты всё это можно просто пустить через HTTPS (SSL).
Плюс FoF
(Тем кто читает это в вебе, можно в принципе и не читать)
Теперь пусть есть некая система типа FoF, в которой действует данный метод глобальной авторизации, и которая должна авторизоваться на доверенных серверах, на которых эта глобальная авторизация тоже действует. Естественно, пароль пользователя хранить в открытом виде в базе при этом нельзя, да его в данных глобальной авторизации и нету. Пример такой ситуации — это FoF (фидридер) — он должен забирать RSS-ленты пользователя, в которых пользователь тоже авторизуется.
- FoF видит в урле рсс’ки &fof_sudo=1, генерирует случайный ID и добавляет в запрос
- Cookie: fof_sudo_id=ID
- Генератор рсс видит cookie fof_sudo_id и делает запрос к fof: /fof-sudo.php?id=ID
- FoF отвечает {'user_name':'user@custis.ru'} и забывает ID
- Генератор рсс принимает тот факт, что теперь он работает под юзером user@custis.ru и отдаёт правильную рсс’ку