Как использовать erl_openid в проектах ChicagoBoss
У нас сейчас есть проект, который работает на ChicagoBoss (это веб-фреймворк на Эрланге). Мы посмотрели несколько библиотек для работы с OpenID и остановились на erl_openid. Так как это единственная библиотека, которая работает с OpenId 2.0. Так как информации о том как использовать erl_openid в сети нет, то мы сами разобрались с этой библиотекой и решили написать статью о том как запустить эту библиотеку.
v.0.1 Пришлось доработать библиотеу
Библиотека на данный момент не может работать с Google OpenID в связи с тем, что Google отказался от поддержки данной технологии. А для работы с Yandex OpenID пришлось допилить саму библиотеку, так как она не совсем правильно отрабатывала по спецификации в части пункта 7.3.1.
Последний абзац этого пункт содержит информацию: If the end user entered an OP Identifier, there is no Claimed Identifier. For the purposes of making OpenID Authentication requests, the value «http://specs.openid.net/auth/2.0/identifier_select» MUST be used as both the Claimed Identifier and the OP-Local Identifier when an OP Identifier is entered.»
В нашем случае мы указываем только OP Identifier при регистрации в Yandex, то вместо Climed ID должны указать «http://specs.openid.net/auth/2.0/identifier_select», а в erl_openid указывался OP Identifer в любом случае.
v.0.2 Запускаем openid_srv и загружаем нужные библиотеки
Мы не нашли красивого способа как автоматически загрузить нужные библиотеки при старте ChicagoBoss сервера. Поэтому сделали следующим образом — создали файл priv/init/project_02_openid.erl следующего содержания:
-module(project_02_openid).
-export([init/0, stop/1]).
init() ->
[application:start(X) || X <- [ crypto, asn1, public_key, ssl, sasl, inets, ibrowse, openid,openid_srv ] ], openid_srv:start_link(openid_srv), {ok, []}. stop(ListOfWatchIDs) ->
[application:stop(X)|| X <-[ crypto, asn1, public_key, ssl, sasl, inets, ibrowse,openid ]].
v.0.3 Запрашиваем OpenID у Yandex
Код следующий:
-module(project_openid_controller, [Req, SessionID]).
-compile(export_all).
-include("openid.hrl").
-define(YANDEX_RETURN_URL, "http://test_project/openid/verify_yandex_openid").
-define(MAIN_URL, "http://test_project/").
-define(YANDEX_OPENID_URL, "http://www.yandex.ru/").
yandex_login('GET', []) ->
AuthReq = gen_server:call(openid_srv, {prepare, SessionID, ?YANDEX_OPENID_URL, true}),
yandex_login_result(AuthReq).
yandex_login_result({ok, AuthReq})->
{redirect, openid:authentication_url(AuthReq, ?YANDEX_RETURN_URL, ?MAIN_URL)};
yandex_login_result({error, Error}) ->
{output, Error}.
Здесь все просто, erl_openid предполагает, что сначала вы сделаете "prepare" запрос к openid_srv. А уже openid_srv сделает предусмотренные спецификацией "Associations" и "Discovery". При этом в запросе указывается три параметра:
- SessionID (обычня строка),
- Discovery_url (тоже строка)
- Cache (true, false значения о том включать ли кэш)
Все запрос сделан, полученный результат обрабатывается и если все хорошо делается редирект на openid:authentication_url
v.0.4 Верификация
К контроллеру project_openid_controller добавляем:
verify_yandex_openid('GET', []) ->
VerifyResult = gen_server:call(openid_srv, {verify, SessionID, ?YANDEX_RETURN_URL, Req:query_params()}),
verify_yandex_openid_result(VerifyResult).
verify_yandex_openid_result({ok, OpenID})->
auth_lib:set_session_login(SessionID, OpenID),
case auth_lib:check_user_profile(OpenID) of
undefined ->
{redirect, "/profile/signup"};
WebUser ->
{redirect, "/"}
end;
verify_yandex_openid_result({error, Error}) ->
{output, Error}.
Здесь смысл простой, после вызова Verify получаем либо OpenID идентификатор либо ошибку. В нашем проекте мы сохраняем OpenID в сессии.
v.1.0 (alfa) Заключение
Мы не стали подробно рассматривать как регистрировать у себя в проекте пользователя после идентификации через OpenID, но я думаю, вы тут и сами разберитесь. А на этом все!