Friday, March 27, 2009

Простейшая реализация OpenID

Документация изначально написана для внутреннего пользования при создании модуля работы с OpenId. Модуль поддерживает только часть функционала openid (только регистрацию по первой версии OpenId). Результат можно посмотреть в здесь. Поддерживает только идентификаторы вида http://имя пользователя с именем провайдера - на этот идентификатор все openid провайдеры должны возвращать свое описание в заголовках страницы. Решил выложить, так как за пол года не появилось более полной реализации по сравнению с той, что есть у меня.

Общие шаги(OpenID *)

Полученному идентификатору запрашиваем страницу в ней ищем значения openid2.provider(OpenId 2.0), openid.delegate (OpenId 1.0 в общем случае должен совпадать с введенным именем пользователя), openid2.local_id(OpenId 2.0 в общем случае должен совпадать с введенным именем пользователя), openid.server (OpenId 1.0) и X-XRDS-Location (OpenId 2.0).

Например:
  • <link rel="openid2.provider" href="http://openid.yandex.ru/server/" />
  • <link rel="openid2.local_id" href="http://openid.yandex.ru/имя пользователя/" />
  • <link rel="openid.server" href="http://openid.yandex.ru/server/" />
  • <meta http-equiv="X-XRDS-Location" content="http://openid.yandex.ru/имя пользователя/yadis/" />
Для OpenId 1.0 Перенаправление пользователя для проверки его валидности

Сделать запрос к серверу (openid.server) на проверку пользователя (openid2.local_id) режим checkid_setup - так как это простейший режим и требующий минимальной реализации с нашей стороны:
  1. [openid.server]?
  2. openid.mode=checkid_setup&
  3. openid.identity=[openid2.local_id]&
  4. openid.return_to=[Путь на который нужно вернуться]&
  5. openid.trust_root=[Проверяем доверие серверу(доменное имя)]&
  6. openid.claimed_id=[openid2.local_id]
Для OpenId 2.0 Получение дополнительной информации

По полученному X-XRDS-Location получаем Yadis документ:
<?xml version="1.0" encoding="UTF-8" ?>
<xrds:XRDS xmlns:xrds="xri://$xrds" xmlns="xri://$xrd*($v*2.0)">
<XRD>
<Service priority="20">
<Type>http://specs.openid.net/auth/2.0/signon</Type>
<Type>http://openid.net/signon/1.0</Type>
<URI>http://openid.yandex.ru/server/</URI>
<LocalID>http://openid.yandex.ru/имя пользователя/</LocalID>
</Service>
</XRD>
</xrds:XRDS>

По нему нужно сформировать адрес перенаправления на сайт провайдера для проверки, но в текущей реализации это не сделано и перенаправление всегда генерируется на основе первой версии OpenId. Вторая версия более сложная в реализации, но позволяет получить дополнительные поля при регистрации (описание пользователя).

Возвращаемый сайтом ответ через обратное переполнение
В результате проверки на сайт мы должны вернуться в любом случае с такими параметрами:
  1. Удачный:
  • [Вернутся на такой url]?
  • openid.assoc_handle=[Тип подписи]&
  • openid.identity=[openid2.local_id]&
  • openid.mode=id_res& (нам доверяют)
  • openid.op_endpoint=[openid.server]&
  • openid.response_nonce=[временной штамп]&
  • openid.return_to=[Вернутся на такой url]&
  • openid.sig=&(подпись)
  • openid.signed=(от каких полей подпись)
  1. Не удачный
  • [Вернутся на такой url]?
  • openid.mode=cancel (вам не доверяют)
Проверка подписи
Для яндекса проверка не сработала, когда я тестировал модуль, возможно я что-то делаю не так. Стандартный код проверки OpenId тоже не делал эту проверку.

После получения мы должны проверить, а те ли нам ответили и запросить с сервера дополнительные сведения:
  • [openid.server]?
  • openid.mode=check_authentication&
  • openid.assoc_handle=[Значение openid.assoc_handle из предыдущего запроса]&
  • openid.sig=[Значение openid.sig из предыдущего запроса]&
  • openid.signed=[Значение openid.signed из предыдущего запроса]&
  • openid.identity=[Значение openid.identity из предыдущего запроса]&
  • openid.return_to=[Значение openid.return_to из предыдущего запроса]

No comments: