Аутентификация с помощью социальных сервисов и 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 'https://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 'https://www.simplecoding.org' (length=27)

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

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

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

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

Source

Заключение.

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

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