Аутентификация с помощью социальных сервисов и OpenId (Loginza)

Владимир | | JavaScript, PHP, Web разработка.

loginza

Приветствую всех!

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

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

Но если вам нужно обеспечить поддержку максимально большого количества сервисов, то объем работы резко возрастает.

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

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

Примечание. Вообще-то Loginza появилась в 2008, но почему-то не попала в поле моего зрения.

На данный момент поддерживается 20 различных сервисов (судя по информации на официальном сайте). Но у меня после установки виджета появились только 17 кнопок. Хотя, все основные сервисы рунета присутствуют.

Прежде чем переходить к примеру, хочу немного рассказать о том, что даст вам аутентификация с помощью сторонних сервисов. Если вы знакомы с протоколами OpenId и OAuth, можете спокойно эту часть пропустить.

Если не вдаваться в детали, то такая аутентификация позволит вам определить, что посетитель является владельцем аккаунта на каком-то сервисе. И получить некоторое количество информации о нём.

Какое именно количество информации вы получите, зависит от сервиса и от самого пользователя. Обычно это данные, которые можно посмотреть в профиле пользователя.

Технически процедура аутентификации происходит следующим образом.

1) Посетитель на вашем сайте нажимает кнопку «Войти с помощью …» и попадает на сайт выбранного сервиса.

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

3) Затем происходит редирект посетителя на ваш сайт и при этом передаётся специальный идентификатор (токен) с помощью которого можно получить данные от сервиса.

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

Это очень упрощенное описание принципа работы всей системы. Но, думаю, даже из него ясны основные достоинства такого метода аутентификации.

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

Теперь возвращаемся к примеру, который я обещал.

Прежде всего, создадим обычную html страничку (index.html) со ссылкой «Войти, используя виджет Loginza».

Выглядеть она может, например, так.

<!doctype html>
<html lang="en" class="no-js">
<head>
  <meta charset="utf-8">

  <!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><![endif]-->

  <title>Loginza test</title>
  <meta name="description" content="">
  <meta name="author" content="">

  <!-- CSS : implied media="all" -->
  <link rel="stylesheet" href="css/style.css?v=1">
 
</head>

<body>

  <div id="container">
    <h1>Loginza test</h1>
    
    <div id="main">
      <a href="https://loginza.ru/api/widget?token_url=http://localhost/sites/tests/loginza/login.php&providers_set=openid,vkontakte,facebook,twitter,google,yandex" class="loginza">Войти, используя виджет Loginza</a>  
    </div>
  </div> <!--! end of #container -->

  <script src="https://s3-eu-west-1.amazonaws.com/s1.loginza.ru/js/widget.js" type="text/javascript"></script>
</body>
</html>

Для подключения виджета нужно создать ссылку при клике по которой будет открываться форма (строка 23) и подключить скрипт (строка 27).

При этом в ссылке можно указать два GET параметра.

token_url – обязательный. В нём передаём адрес скрипта, на который будет выполнен редирект после аутентификации пользователя на выбранном сервисе.

providers_set – необязательный. Здесь указываем перечень сервисов, которые будут показаны виджетом. Допустимые значения: vkontakte, facebook, twitter, loginza, myopenid, webmoney, rambler, flickr, lastfm, openid, mailru, verisign, aol, steam, google, yandex, mailruapi.

Теперь рассмотрим скрипт login.php.

<?php
//если токен не получен, отправляем пользователя на главную страницу
if (!isset($_POST['token'])) {
    header('Location: index.html');
    exit;
}
//отправляем запрос на получение данных пользователя
if (false === ($authData = file_get_contents('http://loginza.ru/api/authinfo?token='.$_POST['token']))) {
    $err = 'Ошибка получения данных';
}

//если данные получены, создаем сессию и добавляем пользователя в БД (опционально)
?>
<!doctype html>
<html lang="en" class="no-js">
<head>
  <meta charset="utf-8">

  <!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><![endif]-->

  <title>Loginza test - login</title>
  <meta name="description" content="">
  <meta name="author" content="">

  <!-- CSS : implied media="all" -->
  <link rel="stylesheet" href="css/style.css?v=1">
</head>

<body>
  <div id="container">
    <h1>Loginza test - login</h1>
    
    <div id="main">
        <?php
        if (isset($err)) {
            echo '<p>'.$err.'</p>';
        }
        else {
            $ad = json_decode($authData);
            var_dump($ad);
        }
        ?>
    </div>   
  </div> <!--! end of #container -->
</body>
</html>

Это демонстрационный вариант. Полезной работы скрипт делает немного.

Вызывается он сервисом Loginza, и в POST параметре получает токен. Этот токен можно использовать для получения данных пользователя. Для этого необходимо отправить запрос к Loginza.API и передать токен в GET параметре (строка 8).

Ответ придет в формате JSON. И с помощью функции json_decode его можно преобразовать в объекты PHP. В этом примере я просто вывел полученные данные с помощью var_dump.

Например, взгляните на данные, полученные после аутентификации на twitter и facebook.

object(stdClass)[1]
  public 'identity' => string 'http://twitter.com/simplecoding' (length=31)
  public 'provider' => string 'http://twitter.com/' (length=19)
  public 'biography' => string 'web, программирование, блоггинг' (length=55)
  public 'photo' => string 'http://a1.twimg.com/profile_images/95090693/photo_189x189_normal.jpg' (length=68)
  public 'nickname' => string 'simplecoding' (length=12)
  public 'web' => 
    object(stdClass)[2]
      public 'default' => string 'http://www.simplecoding.org/' (length=28)
  public 'name' => 
    object(stdClass)[3]
      public 'full_name' => string 'Vladimir Statsenko' (length=18)
      public 'uid' => int 1111111111
object(stdClass)[1]
 public 'identity' => string 'http://www.facebook.com/vladimir.statsenko' (length=42)
 public 'provider' => string 'http://www.facebook.com/' (length=24)
 public 'name' =>  object(stdClass)[2]
	 public 'full_name' => string 'Vladimir Statsenko' (length=18)
	 public 'first_name' => string 'Vladimir' (length=8)
	 public 'last_name' => string 'Statsenko' (length=9)
	 public 'dob' => string 'YYYY-MM-DD' (length=10)
	 public 'gender' => string 'M' (length=1)
	 public 'email' => string 'mymail@mail.com' (length=20)
 public 'web' =>  object(stdClass)[3]
	 public 'default' => string 'http://www.simplecoding.org' (length=27)

Как видите, перечень полей разный, к тому же нет гарантии, что пользователь на сервисе заполнит соответствующие поля.
Например, фотография на facebook у меня установлена, но в полученных данных ссылки на неё нет, а в twitter – есть.

Что делать дальше?

Если аутентификация прошла успешно, то как минимум создавать сессию и отправлять пользователя на страницы с ограниченным доступом. Можно добавить какие-нибудь данные в свою БД, создать аккаунт, если есть необходимость, попросить посетителя ввести недостающие данные. Тут всё зависит от вашего сайта и фантазии 😉

Для тех, у кого есть желание поэкспериментировать, выкладываю архив с примером.

Source

Заключение.

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

По большому счету, основной недостаток при использовании Loginza в том, что ваш ресурс будет зависеть от устойчивости его работы. Но, с другой стороны, вы в любом случае будет зависеть от сторонних сервисов. К тому же, с точки зрения пользователя, работать с вашим сайтом станет гораздо удобнее. Заполнять формы никто не любит 🙂

  • толи я криворукий толи ещё чего но логинза не понимает мой phpMyID

  • Alexei Rudenko

    о, как вовремя) как раз сегодня делал такую штуку. Но две проблемы обнаружил:
    Первая — большая — не все сайты оказываются возвращают эмэйл пользователя. А мне без эмэйла в проекте юзер и не особо нужен..
    Вторая — маленькая — не все провайдер нормально работают. Например, когда я клацал на кнопку рамблера, мне рамблер высветил какую-то невнятную ошибку.

  • А залогиниться на другие сервисы (например, stackoverflow.com) с помощью этого id получается?

    • да. на жж, в блогспоте — постоянно использую уже пару лет. вот и сюда с openid пишу

      • Насколько я понял, разработка phpMyID прекращена в 2008 году.
        Loginza является OpenID 2.0 провайдером и появилась в 2008. Возможно, у них проблемы с поддержкой предыдущих версий стандарта (OpenID 1.1 или OpenID 1.0). Но это только мои предположения.

  • С email все просто. Стандарт (openid) не требует, чтобы пользователь его вводил, поэтому либо отказываетесь от поддержки всех сервисов, которые email не возвращают, либо сразу после аутентификации показываете пользователю страницы профиля и в обязательном порядке требуете ввести email. Без этого не активируете аккаунт.

    Со второй проблемой сложнее. Как заставить рамблер правильно работать я не знаю 🙂

  • Если внедрять систему единой авторизации с поддержкой разных сервисов, какие данные у пользователя будут уникальные?

    Пример:
    если с твитере есть пользовать XXX и у кокого то OpenID провайдера тоже есть пользователи XXX (логин 1) как их различать ?
    возможно XXX@service.com ?

    разделять еще ясно, предложить ему ввести емейл который будет уникальный но какой логин (ник) выводить на сайте ?

  • Спасибо за статью. Количество различных сервисов в глобальной сети растет и единая авторизация в скорем времени будет необходимостью…

  • Уникальной будет комбинация из названия провайдера и uid, который этот провайдер возвращает.
    @ между ними ставить не обязательно.

    С логином немного сложнее. Можно указывать тот, который возвращает сервис аутентификации.

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

  • Александр

    Владимир, спасибо за статью об этом сервисе.
    Подскажите, а каким полям можно однозначно доверять, что они всегда заполнены ? Ну например nickname наверняка всегда в ответе не пустой приходит ?

    • Когда вы работаете со сторонним сервисом, то, по большому счету, доверять ничему нельзя. Данные всегда нужно проверять. Если я не ошибаюсь гарантированы только identity и provider, хотя не уверен.

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

      Вообще вопрос интересный и я планирую небольшую статью на эту тему 🙂

  • Pingback: Особое программирование » Post Topic » Как «подружить» сервис Loginza и фреймворк Yii()

  • Pingback: Чертова креативность()

  • Andrey

    вы бы скрины показали ато не совсем понятно как это работает

    • Тут не с чего скриншоты делать.
      Стандартное окно Loginza (оно в начале статьи показано), а потом
      только фраза Loginza test — login и данные пользователя.

      Вы получите гораздо больше информации если потестируете этот пример
      (архив в конце статьи).

  • Большое спасибо за статью. Тоже давно задумывался облегчить жизнь пользователям.

    Расскажу некоторый свой опыт как пользователя сайтов с логинзой. Логинза поддерживает много разных сервисов, на многих из которых у меня есть аккаунт. Я зашел на некоторый сайт впервые. Использовал для этого логинзу и мой аккаунт вконтакте.

    Прихожу я на этот же сайт с работы, или просто через время. Точно помню что регался, но не помню какой сервис использовал.
    Я на том сайте оставлял сообщения, качал файлы и поддерживал рейтинг на трекере, и хочу таки залогинится «своим старым прокачанным пользователем»

    Мне прийдется угадывать (авторизироваться разными сервисами и создавать мёртвые души).

    Вышеописанная ситуация это одно из наиболее узких мест.

    Еще одно узкое место — это уникальность имён пользователей. Или все считают что уникальность имени пользователя это пережитки прошлого? Что делать если пользователь с таким же именем уже существует?

    • Стандартная проблема — чем больше возможностей, тем больше вопросов 😉

      К имени можно добавить название сервиса. Вообще я не знаю хорошего решения в такой ситуации. С одной стороны, имена вроде «Вася1111» — не красиво. С другой — несколько пользователей с одинаковыми именами — будет путаница, особенно в комментариях.

      Частично решают проблему аватарки.

  • Hakk43mag

    ни как не могу поставить на сайт, пишет ошибка 404,
    что это может быть?

    • В какой именно момент вы видите 404-ую ошибку?

      • Hakk43mag

        исправил 404, теперь появилась ошибка 403.
        выход когда перенаправляет на LOgin.php

        • 403 — доступ запрещен.
          Вы уверены, что перенаправляете на существующий скрипт? Ошибка возникает если напрямую (из браузера) обратиться к login.php?

  • Доброго времени суток!
    У меня вообще не понятная проблема.
    Пример:
    Я авторизуюсь через любую (например Твитер) соц сеть,
    Вроде всё норм проходит, переадресовывает на указанную мной страницу.
    И вот здесь появляется проблема, Я не авторизован, И не создан мой акаунт.
    Подскажите что мне делать?
    Почему так?

    • После переадресации ваша страница должна аутентифицировать вас и создать сессию (пример кода в login.php). Т.е. проблема в вашем скрипте. Запустите его с отладчиком и проверьте его работу.

  • На одном из моих сайтов от пользователей много жалоб на такой способ аутентификации стало поступать после включения такой возможности. После входа в соцсеть сайт и перехода  сайт не видит что пользователь авторизован.

    К сожалению сейчас нет времени разбираться в причинах, пока от этой реализации мы отказались. Функция весьма полезная учитывая исключительное трудолюбие среднего пользователя, лишний раз логин пароль ввести это труд неподъемный, не говоря уже про установку чего то вроде Робоформа.

    • Дело не только в заполнении формы с логином и паролем. Нужно еще пройти регистрацию 😉
      А если серьезно, то аутентификация через соц. сети упрощает идентификацию пользователя, прежде всего другими пользователями.

      Вы, как администратор, в любом случае сможете отличить одного пользователя от другого. Но если ваш сайт позволяет использовать одинаковые ники и не требует подтверждения регистрации через email, то любой посетитель сможет что-нибудь написать от чужого имени.

  • Arhi

    Есть ли список сервисов, которые выдают e-mail?

    • Нет, у многих сервисов пользователь может контролировать передачу email. Более-менее гарантировано можно получить email от тех сервисов, в которых он является логином.

  • тест

    тест дискуса

  • test

    test