Javascript виджет авторизации OpenID

    Где то полгода назад я сильно увлекся OpenID и всем что с ним связанно. Моим главным занятием в это время стало — неспешное чтение спецификаций, форумов, блогов и хабрапостов OpenID тематики.

    Все знания, которые мной были получены за это время, я «материализовал» в проекте компании, в которой собственно я работаю.

    Изучая спецификацию OpenID и прочих его расширениях (SREG, AX) и надстройках, мне пришла идея разработать JavaScript виджет со своим API-прослойкой, в помощь другим разработчикам нежелающим «коротать» дни и ночи изучая спеки различных способов авторизации и их расширений.

    Собственно об этом далее.

    Что делает данный виджет?


    Задача, поставленная перед виджетом, была проста, предоставить простой и понятный для конечного пользователя интерфейс авторизации через OpenID. В тоже время виджет является по сути консумером OpenID авторизации.

    Всем известно, что термин OpenID знаком не всем обычным интернетчикам. Поэтому в UI виджета минимум такой терминологии.

    Вот что получилось:
    image image image

    Как работает виджет и как его использовать?


    Как я упоминал выше, виджет не просто UI, но и рабочий консумер. Он полностью берет процесс авторизации пользователя на себя, а с конечным сайтом (который его использует), общается посредством простого API.

    Использовать виджет легко, надо лишь установить на страницу следующий HTML-код:

    <script src="http://loginza.ru/js/widget.js" type="text/javascript"></script>
    <a href="https://loginza.ru/api/widget?token_url=[RETURN_URL]" id="loginza">Войти через OpenID</a>


    * This source code was highlighted with Source Code Highlighter.


    После авторизации пользователя, он будет переадресован на страницу [RETURN_URL], указанную в параметре token_url. На эту страницу в POST будет передан уникальный ключ token, необходимый для получения профиля авторизованного пользователя (данные профиля «тянутся» через SREG расширение OpenID).

    Для того чтобы получить профиль, необходимо сделать межсерверный запрос на URL:

    http://loginza.ru/api/authinfo?token=[TOKEN_KEY_VALUE]

    где [TOKEN_KEY_VALUE] и есть секретный ключ, полученный в POST.

    Формат данных профиля JSON массив с данными о юзере который прошел авторизацию. Пример:

    {"identity":"http:\/\/admin.loginza.ru\/","provider":"http:\/\/loginza.ru\/server\/",
    "name":{"full_name":"\u0421\u0435\u0440\u0433\u0435\u0439 \u0421\u0435\u0440\u0433\u0435\u0439"},
    "nickname":"admin","email":"admin@loginza.ru","gender":"M","dob":"1985-01-31"}


    * This source code was highlighted with Source Code Highlighter.


    Собственно вот такой простой получился, но в тоже время функциональный, способ авторизации OpenID пользователей с подгрузкой данных профиля.

    TODO

    • В планах реализовать обратную совместимость с OpenID 1.0 (на данный момент, поддерживается только 2.0 версия);
    • Добавить поддержку микроформатов hCard, vCard;


    Заключение


    Выношу на критику свою работу, так как хочу получить обратный отклик от разработчиков, мнение и отзывы о полезности данного варианта виджета для них. Стоит ли развивать идею, подключать поддержку других типов авторизации помимо OpenID (Вконтакте, Twitter, Windows Live и тп.) в данном виджете.

    Кому интересно увидеть сам виджет в работе, то сейчас он используется тут в бета режиме.

    UPD (5 мая):
    Рад сообщить, сегодня (5 мая) мы в обновили наш JavaScript виджет OpenID Loginza. Внесены следующие исправления и добавлены функции:

    1. Реализована поддержка Вконтакте OpenAPI в виджете авторизации. Профиль пользователя ВКонтакте передается в нормализованой форме (едином формате), как и при выборе других провайдеров;

    2. Теперь можно создавать несколько ссылок на JavaScript виджет Loginza, для этого укажите в нужных ссылках параметр class=«loginza»;

    3. Была проблема OpenID авторизации на др. сайтах, если логин Loginza имел символы в верхнем регистре. Исправили, теперь работает как часы;

    4. Повышена безопастность авторизации, теперь мы используем https.

    UPD (11 июля):
    Добавлена долгожданная возможность, которую ждали многие:
    параметр providers_set — он отвечает за набор провайдеров авторизации в виджете Loginza.

    Если Вам необходимо ограничить набор кнопок провайдеров доступных пользователям или изменить их порядок, то используйте этот параметр в адресе href ссылки на виджет. Порядок кнопок будет соответствовать порядку перечисления провайдеров в параметре providers_set.
    Поделиться публикацией
    Похожие публикации
    Ммм, длинные выходные!
    Самое время просмотреть заказы на Фрилансим.
    Мне повезёт!
    Реклама
    Комментарии 70
    • +4
      Ухты, превосходно, давно ждал чего либо подобного.

      еще бы хотелось более подробного и такого же простого описания, как интегрировать опенид в свой проект.
      • +1
        Спасибо! Постараюсь, как-нибудь собрать все свои силы и мысли и написать мануал по теме OpenID, основанный на моем опыте. Так как действительно, очень-очень мало документации по OpenID на русском.
        • +1
          а вы пробовали такое искать? ; ) ведь уже достаточно давно существует, например, rpxnow.com — аналог описанного в посте
          • 0
            Да конечно, я на него наткнулся когда уже большая часть работы была проделана. Я не стал останавливаться, так как, я думаю, нашему разработчику не помешает русскоязычный, а главное бесплатный аналог данного сервиса.
            • 0
              А есть бесплатные аналоги?
        • 0
          А как решается проблема с тем что например livejournal не возвращает данные о пользователе (ну или может у меня руки кривые)?
          Выглядит очень симпатично, если бы еще не редайректил на отдельную страничку, а всплывал отдельным слоем, было бы еще лучше имхо.
          • 0
            Если OpenID провайдер не возвращает профиля пользователя, то в JSON массиве соответственно его тоже не будет. Будет переданы данные о identity пользователя и ссылка на провайдера provider.
            • 0
              > если бы еще не редайректил на отдельную страничку, а всплывал отдельным слоем, было бы еще лучше имхо.

              Так же так и сделано (всплывает отдельным слоем), просто видимо у тебя страница не догрузилась или JS, именно для таких случаев сделано так (редирект), чтобы все работало.
            • +1
              > В планах реализовать обратную совместимость с OpenID 1.0 (на данный момент, поддерживается только 2.0 версия)
              а как можно определить, используется ли вторая или первая версия протокола OpenID-сервером?

              разработка однозначно полезная и нужная
              • +1
                Определение версии OpenID сервера сделано очень хитро. Для того чтобы узнать какие версии держит какой либо сервер, нужно обратиться к XRDS документу сервера (путь к нему может передаваться в HTTP-заголовке X-XRDS-Location ответа сервера).

                Собственно в этом документе описывается все возможности сервера:

                1. <?xml version="1.0" encoding="UTF-8"?>
                2. <xrds:XRDS
                3.   xmlns:xrds="xri://$xrds"
                4.   xmlns="xri://$xrd*($v*2.0)">
                5.  <XRD>
                6.   <Service priority="0">
                7.    <Type>httр://specs.openid.net/auth/2.0/server</Type>
                8.    <Type>httр://openid.net/extensions/sreg/1.1</Type>
                9.    <Type>httр://openid.net/srv/ax/1.0</Type>
                10.    <Type>httр://specs.openid.net/extensions/ui/1.0/mode/popup</Type>
                11.    <URI>httрs://loginza.ru/server/</URI>
                12.   </Service>
                13.  </XRD>
                14. </xrds:XRDS>
                * This source code was highlighted with Source Code Highlighter.


                httр://specs.openid.net/auth/2.0/server — как раз указывает на то, что используется 2.0 версия.
                • 0
                  Спасибо за инфу про X-XRDS-Location.
                  Теперь я знаю как работает open-id через Гуглопрофили.
              • +6
                а почему нет поддержки кастомного OpenID? Или как, например, я сделал просто добавил ссылки на openid сервер и профайл на своем сайте и могу теперь использовать свой сайт для авторизации (как делать написано тут — simonwillison.net/2006/Dec/19/openid/ )
                • 0
                  Ппопробывал и через Google аккаунт и через loginza.ru, все хорошо работает но когда на экране остаеться последняя кнопка «Continue» то нажатие на нее обсалютно ничего не дает (Mac Os, Google Chrome), была у меня однажды проблема, что в хроме не работал submit формы на Javascript, возможно причина в этом
                  • 0
                    Сегодня проверю работоспособность Chrome. Будем искать баги :) Спасибо!
                    • +1
                      Та же фигня, только Windows, Opera 10.51
                    • 0
                      в избранные! спасибо!
                      • +1
                        Может быть немного оффтопик, но неужели Mail.ru OpenID ДЕЙСТВИТЕЛЬНО работает? Везде, где я не искал говорят, что это всего лишь заглушка.
                        • 0
                          Раньше — да, действительно не работало, но с недавнего времени (может месяца два назад, или три, точно не помню), они все переработали и исправили баги. Теперь работает на ура.
                          • 0
                            да, работает
                            раньше сначала криво работало, потом нормально работало, но не на всех почтовых адресах, теперь вроде работает везде — по крайней мере у меня на всех ящиках работает

                            только вот на loginza насколько я понял не работает авторизация с других адресов mail.ru, таких как inbox.ru — а это достаточно большая аудитория
                            • 0
                              правда с серверной стороны пришлось сделать костыль специально для обработки их sreg (стандартным обработчиком данные не выдавались, но возможно, что это я где-то накосячил)
                              • 0
                                > не работает авторизация с других адресов mail.ru, таких как inbox.ru

                                Спасибо, я про это совсем забыл, буду исправлять.
                                • 0
                                  Теперь с адресов таких как inbox.ru и т.п. авторизация доступна через api.mail.ru
                            • –5
                              > Где то полгода назад я сильно увлекся OpenID

                              Интересное увлечение. А функцией printf вы не увлекаетесь?
                              • +1
                                Впрочем, виджет полезный, спасибо.
                              • 0
                                Может, выложите исходники на GitHub? Или проект монетизирован?
                                • 0
                                  а https://openid.wmkeeper.com/ не добавите ли?
                                • 0
                                  <a href="javascript:LOGINZA.newUser();">Зарегистрируйтесь</a>

                                  Не работает. По клику ничего не происходит.
                                  Chromium 5.0.368.0 (43430) Ubuntu
                                • 0
                                  Спасибо большое!
                                  Буду рад обновлению с поддержкой первой версии openid, чтобы можно было использовать без опасений.
                                  • 0
                                    Большое спасибо, очень интересный вариант для авторизации пользователей, буду пробовать.
                                    Скажите, а локализация интерфейса на другие языки есть/планируется? Навскидку на вашем сайте ничего по этому поводу не нашел…
                                    • 0
                                      Да, планируется. Еще и редактор интерфейса, чтобы самому настраивать порядок иконок провайдеров и их количество в виджете.
                                      • 0
                                        Сделали настройку порядка и набора иконок авторизации в виджете.
                                    • 0
                                      Напомните кто-нибудь зачем экранировать / в json?:
                                      http:\/\/admin.loginza.ru
                                      • 0
                                        Была бы еще опция — при отсутствии учетных записей на сервисах из списка — просто возвращать на сайт с каким-либо специальным параметром, чтобы пользователя можно было зарегистрировать у себя, а не регистрировать на Логинзе и у себя.
                                        • 0
                                          оо, спасибо, только сегодня подумал, что на всяких разных форумах надо бы делать сквозную или внешнюю авторизацию. Буду использовать, с вашего разрешения :-)
                                          • 0
                                            монетезироваться то будете?
                                            • 0
                                              Пока в планах такого не было, да и еще очень рано об этом думать.
                                            • 0
                                              Да, последнее время мне тоже приходится работать с технологией OpenID, но на мой взгляд большой минус в количестве сайтов предоставляющих авторизацию и что самое плохое они возвращают разные наборы данных о пользователе что не очень-то удобно. На мой взгляд я бы предложил другой вариант реализации подобной технологии в двух вариантах:

                                              1. Унификация данных пользователей везде (стандартизированный набор данных всех возможных вариантов), чтобы если где-то заполняется профиль
                                              пользователя, то сразу всей необходимой информацией (пользователь естественно сам решает что и когда ему следует заполнить). Также для более продвинутых пользователей есть возможность установить собственный OpenID сервер для собственной учётной записи или даже нескольких для разных случаев (всякое бывает :)).

                                              2. Создание клиентского приложения в котором пользователь сохраняет все свои данные (что не требует кстати доступа в интернет, и данные хранятся в большей безопасности на его компьютере допустим в зашифрованном виде и доступ к ним есть только у программы через мастер пароль например), и при авторизации на сайтах данная программа выступает в качестве OpenID сервера.

                                              Таким образом достичь надо следующего: все данные должны хранится в одном месте, а потребители этих данных будут запрашивать необходимые записи (стандартизированные) и после разрешения пользователя на предоставление тех или иных данных они будут им переданы.

                                              Лично для себя я сейчас рассматриваю вариант 2, создания такого приложения-паспорта, лично мне он кажется гораздо более удобным вариантом, его например даже можно носить на внешнем носителе, что позволит авторизоваться даже с чужих машин. Пока в стадии проектирования и сбора данных (месяц назад всего начал), если будут заинтересовавшиеся то с радостью поделюсь мыслями, приложение планирую делать open source на базе sourceforge.org так что буду рад если найдутся единомышленники.
                                              • 0
                                                Ммм… очень интересная идея, даже очень… Но сразу возник вопрос, а как будет проводиться проверка подлинности введенной информации, то есть какие гарантии будут того, что пользователь предоставляет реальные данные, а не от «балды»?
                                                • 0
                                                  Встречный вопрос, а сейчас на сайтах данные разве проверяются? OpenID сервер возвращает то что ввёл пользователь, а что он там ввёл никто не смотрит. Подлинность это уже совсем другой вопрос, сначала надо сделать систему авторизации единую, а потом уже к ней придумывать систему проверки подлинности :)
                                                  • 0
                                                    Ну в случае серверного хранения данных (на конкретном OpenID сервере), в какой то степени есть малось централизации. Ну а если делать такую программу, то полная децентрализация. То есть пользователь полностью сам по себе. Возможно я ошибаюсь, просто сразу возникла такая мысль — рай для «спамеров».
                                                    • 0
                                                      Да, просто рассматривая вопрос централизации хранения данных я решил пойти обратным путем и рассмотрел централизацию просто в другом месте, не чтобы всех пользователей собрать на сервере, а чтобы все данные пользователя собрать у него самого :)

                                                      Никаких новых проблем это не привносит как таковых если подумать и рая для спаммеров не создаёт, потому что это та же OpenID авторизация только с сервером на компьютере пользователя, поэтому всё что работает сейчас может работать и дальше также.
                                                      • 0
                                                        Немного поясню ещё отличия и почему я решил именно перенести всё к пользователю. Рассмотрим например сайт hh.ru, пользователь заходит на него, нажимает регистарция, сайт запрашивает от него некий набор данных, пользователь подтверждает передачу (можно настроить для каких полей подтверждать, а какие отдавать без вопросов) и всё, он зарегистрирован. Дальше также необходимо подтвердить емайл допустим активировав аккаунт. После этого он заполняет резюме, причём данные уже могут быть вбиты в его локальный паспорт и он опять же просто подтверждает их передачу сайту.

                                                        А касательно спаммеров все методы защиты остаются такими же, устраняется лишь необходимость заполнения форм личными данными и автоматическое обновление данных на сайте при его посещении в случае изменения данных в паспорте.
                                                        • 0
                                                          Про меры борьбы со спамом в OpenID:
                                                          — сайты принимающие авторизацию по OpenID, могут если увидят что какой то сервер грешит спам учетками, просто запретить регистрацию пользователей с него.
                                                          — OpenID сервер знает о своих пользователях некоторый набор данных по его активности, и может ввести показатель доверия, который будет доступен сторонним сайтам (кстати такой рейтинг хотят сделать на OpenID.Яндекса, о чем писалось тут)

                                                          Еще ссылки про спам проблемы:
                                                          • 0
                                                            ой, ссылки забыл дать:
                                                            Планы яндекса источник
                                                            Есть интересная идея придумать (или найти придуманный) протокол, которым Яндекс сможет сообщать целевому сайту относительный уровень доверия пользователю. Сейчас у сайта, который принимает яндексового юзера, есть уверенность только в том, что это не робот, потому что у нас есть CAPTCHA при регистрации. Но ведь мы на стороне сервера знаем, какими сервисами пользуется юзер, а значит можем прикинуть, что если пользователь активно пишет в свой ярушный блог и регулярно загружает фотки, то это скорее всего не спамер, а нормальный сетянин.


                                                            А вот полная децентрализация не позволит этого сделать.
                                                            • +1
                                                              Ну на самом деле децентрализация совсем не помешает сделать тоже самое, и можно будет проверять активность даже не по одному сервису, а по нескольким. Ниже подробнее отписался, конечно остаётся вопрос как технически надёжнее это сделать, но и на него я думаю ответ со временем найдётся.
                                                            • 0
                                                              Ну есть о чём подумать, конечно, но вводить критерии доверия от разных сайтов можно и при хранении данных у пользователя.

                                                              По описанному выше: блочить весь сервер при большом количестве спам учёток на нём это слишком категорично, такие действия не должны затрагивать других пользователей.

                                                              Я бы предложил такую схему: в локальном паспорте пользователя хранить информацию о сервисах где он зарегистрирован, тогда при авторизации на неком новом сайте А, тот может проверить зарегистрирован-ли пользователь на одном из сайтов которому А доверяет. Если такой сайт есть, то с него по токену пользователя запрашивается некий показатель доверия. Так даже можно несколько сайтов проверить. А если на этом сайте А пользователь будет спамить, то его кредит доверия на сайтах которые его подтвердили аннулируется.

                                                              Ну на самом деле защита от спама вопрос сложный, сходу конечно такие решения сложно сделать, надо рассматривать множество случаев и это дело далеко не одного дня.

                                                              PS А ссылочки заново запостите, а то что-то я их не вижу.
                                                  • +2
                                                    1. Чтобы авторизоваться надо пройти 5 (!!!) шагов. Вся прелесть OpenID в минимизации усилий. Регистрация должна быть в 2 шага: нажал кнопку на сайте, где хочешь авторизоваться, подтвердил на сайте провайдера OpenID. Как этого достичь — проблема юзабилиста.

                                                    2. В Рамблере можно авторизоваться без ввода e-mail. Просто по урлу.

                                                    3. В форме регистрации подсказки находятся «где-то рядом».


                                                    4. Что станет с авторизацией, если loginza.ru постигнет хабраэффект или попросту взломают сервак?
                                                    • 0
                                                      > В Рамблере можно авторизоваться без ввода e-mail. Просто по урлу.

                                                      Можно про это поподробнее, что имелось в виду и где на это посмотреть?
                                                      • 0
                                                        Авторизация на рамблере происходит аналогично яндексу и гугл. Урл для авторизации:
                                                        http://id.rambler.ru/script/openid.cgi

                                                        Примеры: moiplan.ru pip.ec
                                                        • 0
                                                          А где Вы видели авторизацию OpenID по email?

                                                          Я не понимаю суть Вашего замечания:
                                                          >2. В Рамблере можно авторизоваться без ввода e-mail. Просто по урлу.
                                                          • +1
                                                            Хорошо, возможно слово e-mail здесь не самое подходящее, хотя суть отражает. Смысл в том, что я захожу на ваш сайт, жму войти, выбираю рамблер, мне пишет: «Введите логин Вашей учетной записи». Зачем? Это еще одно лишнее и ненужное действие. Я привел примеры где данная возможность реализована без ввода дополнительных данных.
                                                            • 0
                                                              А теперь все понятно :) Сенкс, будем пробовать.
                                                    • +4
                                                      Я вас поздравляю, вы сделали из секьюрного протокола несекьюрный =)
                                                      теперь если вы залогинились на одном сайте с вашим виджетом и поставили галочку «запомнить», вы автоматически залогинились на всех сайтах, где стоит этот виджет.
                                                      • 0
                                                        Это легко поправимо, сделаем просто уникальный realm (например https://loginza.ru/api/realmKeyUnique/) для каждого token_url. Спасибо, за найденный недочет!
                                                        • 0
                                                          Собственно, уже исправили.
                                                      • 0
                                                        Удобный инструмент, поставил себе на ряд проектов. Нюансы на которые я обратил внимание:
                                                        — Не хватает удобной возможности легко выбирать из всех способов авторизации те, которые нужны именно под конкретный проект
                                                        — Не хватает готовых модулей для популярных CMS с набором функционала

                                                        Всё остальное вери гут, большое спасибо и удачного развития проекту. Очень и очень радует.
                                                        • 0
                                                          Ну и добавлю, поработайте над безопасностью, есть ряд небольших, но дырок. Стоит закрыть.
                                                          • 0
                                                            Вопрос решили, нет там дырки. Ошибочка вышла.
                                                          • 0
                                                            Из модулей есть Wordpress наш официальный плагин loginza.ru/wp-plugin
                                                            Ну и недавно написанный Drupal плагин docs.drupal.ru/node/45330 от Обухова Никиты
                                                          • 0
                                                            Скажите, а зачем логинза хочет получить список моих контактов с гугла?
                                                            • 0
                                                              Получение собственного контакта self и др. контактов имеет одинаковое разрешение. Ваши контакты Логинза не получает, запрашиваются только данные профиля.
                                                              • 0
                                                                то есть, если я правильно понял, из-за того, што гугл не сделал отдельное разрешение, приходится выдавать логинзе (теоретическую) возможность прочитать список моих контактов?
                                                                • 0
                                                                  Да. Если Вы знаете др. разрешение только на чтение профиля, сообщите.
                                                          • 0
                                                            Установил Логинзу на свой проект. Все отлично работает, но есть нюанс. Под окошком Логинзы синий квадратный фон, и он выглядит очень коряво. Нельзя ли что-то с этим сделать?
                                                            • 0
                                                              Та же беда, не нагуглил ничего.

                                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.