Pull to refresh

Социальный логин: cильные стороны

Reading time 9 min
Views 15K


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

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

Решают ли библиотеки все задачи?

Что хотят пользователь и владелец приложения



Как пользователь приложения, я хотел бы иметь возможность объединять несколько социальных аккаунтов в один. Определённо, я не хочу потерять доступ к приложению, потеряв доступ к социальному аккаунту. Или оказаться в ситуации, когда я вынужден продолжать использовать определённый социальный аккаунт лишь только по той причине, что он когда-то использовался для регистрации в приложении. Если использую несколько приложений, объединённых одним брендом (например, GMail и Google+), я ожидаю, что после логина или регистрации в одном из них мне так же будут доступны и другие, без необходимости повторного логина или регистрации. Если у меня появляются причины полагать, что доступ к моему аккаунту попал в чужие руки (возможно, после совершения логина в публичном месте), я хотел бы иметь возможность отозвать все ранее выпущенные токены доступа и, таким образом, заблокировать не желательный доступ к моему аккаунту.

Как владелец приложения, я не хотел бы тратить время на интеграцию социального логина каждый раз когда начинаю новый проект. Иметь рабочую версию сейчас, настройки позже, после запуска проекта. Если проект может быть выполнен в виде браузерного (фронтенд) или мобильного приложения, на их реализации и сконцентрировать свое внимание. Разворачивать серверное приложение и хранилище данных, только для целей социального логина, совсем не то, чем я хотел бы заниматься, работая над таким проектом. В то время как, не использовать серверное приложение для социального логина, означает отсутствие каких-либо гарантий того, что данные пользователя не будут разоблачены злоумышленнику, а токен доступа не будет подменен. В случае, с разработкой веб-сервиса (фронтенд + бэкенд), взаимодействие его компонентов должно быть простым и эффективным. Вероятно, я не захочу использовать токены выпущенные провайдером социального логина и требующие для валидации внешнего запроса к серверу провайдера. Могу захотеть выпустить собственные, на базе которых могут быть постороены SSO и Federated identity. Определённо, хочу иметь механизмы отзыва (аннулирования) токенов доступа. Наличие административного приложения могло бы упросить для меня доступ к информации о пользователях.

Аутентификация как сервис



Озвученные выше задачи могут быть решены в рамках веб-сервиса. В примерах ниже, используется веб-сервис PolyAuth. Цель которого — максимально упростить интеграцию аутентификации в приложение, за счёт единого API, стандартизированного формата данных профиля, необходимых инструментов и инфраструктуры. Доступно два, различных по применению, API для целей аутентификации и доступа к данным. Standalone Authentication API обеспечивает базовый функционал социального логина, быстрый старт и возможности, которые будут описаны ниже в примерах. Это API предоставляется в свободном доступе, без каких-либо платежей и лимитов на запросы. Main Authentication API обеспечивает расширенный функционал и нацелен на решение более широкого круга задач:

  • Быстрый старт. Будь то новый проект или существующий, интеграция не должна отнимать время. Рабочая версия сейчас, настройки позже.
  • Социальный логин. Логин с использованием Google, Facebook, и других провайдеров.
  • Стандартизированный профиль. Профиль пользователя в едином формате.
  • Много провайдеров — Один Пользователь. Объединение нескольких социальных аккаунтов в единый аккаунт пользователя.
  • Управление токенами. Выпуск, отзыв (аннулирование) и валидация токенов.
  • Single Sign-On (SSO). Когда приложений несколько, логин в одном позволяет пользователю получить доступ к ресурсам других без повторного логина.
  • Federated identity. Одно приложение может делегировать выполнение задач и получать ресурсы пользователя управляемые другими приложениями.
  • Поддержка безсерверных приложений. Для проектов которые могут быть выполнены в виде браузерного (фронтенд) или мобильного приложения, интеграция социального логина не должна накладывать дополнительных требований.
  • Административное приложение. Информация о пользователях и возможность совершения операций над ними должна быть доступна владельцу приложения в виде простого и понятного графического интерфейса.


Перед началом работы потребуется создать аккаунт и группу для будущих пользователей (realm). Указать URI приложения, куда пользователи будут отправлены после того как они делегируют доступ к их данным.

Аутентификация в браузерном приложении, веб-компоненты



Схема взаимодействия приложения с сервисом



С веб-компонентами, интеграция выглядит много проще, чем на схеме. Для их установки, используем Bower:

$ bower install --save \
	polyauth-elements/polyauth-element \
	polyauth-elements/polyauth-signin-pages \
	fetch


Для импорта — необходимо включить следующие строки в <head> секцию HTML документа:

<script src='bower_components/fetch/fetch.js'></script>
<script src='webcomponentsjs/webcomponents-lite.min.js'></script>
<link rel='import' href='bower_components/polyauth-elements/polyauth-element.html'>


Для совместимости с версиями браузеров не имеющих реализации WebComponents и Fetch API импортируются полифилы. В примерах, так же, будут использоваться дополнительные веб-компоненты. Их перечень, как и весь исходный код примеров доступны на GitHub.

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



<template is='dom-repeat' items='[[endpoints]]'>
  <a href='[[item.authCodeURI]]'>
    <iron-icon icon$='[[item.icon]]'></iron-icon>
  </a>
</template>

<polyauth-authcode-endpoints
  apiv='v1'
  realm-id='REALM_ID'
  redirect-uri='REDIRECT_URI'
  objects='{{endpoints}}'>
</polyauth-authcode-endpoints>


После того как пользователь делегирует права доступа к его данным, он перенаправляется провайдером обратно в приложение со специальным кодом, который в дальнейшем может быть обменян на токен доступа (в соответствии с OAuth2 Authorization Code Grant). Токен доступа сохраняется приложением в локальном хранилище для повторного использования. Описанная схема полностью реализована в веб-компоненте polyauth-signin-pages, который кроме прочего, прячет форму аутентификации.

<polyauth-signin-pages
  apiv='v1'
  realm-id='REALM_ID'
  access-token='{{token}}'
  auto>

  <section signed-out>
    <!-- Этот блок увидят пользователи,
        которые еще не выполнили вход -->

    <template is='dom-repeat' items='[[endpoints]]'>
      <a href='[[item.authCodeURI]]'>
        <iron-icon icon$='[[item.icon]]'></iron-icon>
      </a>
    </template>
  </section>

  <section signed-in>
    <!-- Этот блок увидят пользователи,
         которые выполнили вход -->
  </section>

</polyauth-signin-pages>


Имея токен доступа, можно получить профиль пользователя и отобразить его аватар и сообщение приветствия:



<iron-image src='[[profile.data.info.image]]'></iron-image>
<div>Hello, <span>[[profile.data.info.name]]</span>!</div>

<polyauth-profile
  apiv='v1'
  access-token='[[token]]'
  object-id='me'
  object='{{profile}}'
  auto>
</polyauth-profile>


Для кнопки выхода, потребуется одним HTML тегом больше.

<button polyauth-sign-out>Sign Out</button>


Объединить несколько аутентификационных записей под одним аккаунтом пользователя, не многим сложнее:



<polyauth-user
  apiv='v1'
  access-token='[[token]]'
  object-id='me'
  fields='["profile", "auth"]'
  object='{{user}}'
  auto>
</polyauth-user>

<polyauth-user-authlinks
  id='authLinksProxy'
  apiv='v1'
  realm-id='REALM_ID'
  redirect-uri='REDIRECT_URI'
  access-token='[[token]]'
  user-id='me'
  objects='[[user.auth]]'
  objects-proxy='{{authLinks}}'>
</polyauth-user-authlinks>

<template is='dom-repeat' items='[[authLinks]]'>
  <iron-icon icon$='[[item.icon]]'></iron-icon>
  <paper-toggle-button
    checked='[[!item.removed]]'
    on-change='_handleAuthLink'>
  </paper-toggle-button>
</template>


Для этой задачи потребуется JavaScript функция-обработчик события:

_handleAuthLink: function(e) {
    this.$.authLinksProxy.handle(e.model.index);
}


Аутентификация в браузерном приложении, JavaScript



JavaScript библиотека может быть установлена с помощью Bower:

$ bower install --save fetch polyauth


Для импорта — необходимо включить следующие строки в <head> секцию HTML документа:

<script src='bower_components/fetch/fetch.js'></script>
<script src='bower_components/polyauth/polyauth.js'></script>


Выполнить логин и получить профиль пользователя можно следующим образом:

// Перенаправление пользователя на страницу провайдера
window.location.href =
  PolyAuth.authCodeURI(REALM_ID, {
    apiv: 'v1',
    key: 'oauth2.google-plus',
    redirectURI: REDIRECT_URI
  }

// Получение профиля пользователя
PolyAuth
  .signIn(REALM_ID)
  .then(function(resp) {
    PolyAuth
      .fetch(PolyAuth.api(resp.accessToken, 'v1').profile('me').get())
      .then(function(object) {
          console.log(resp);
      });
   });

// {
//   "id": "8c63a8cb-b3dd-4772-b133-169f4b3d5e47",
//   "data": {
//       "info": {
//         "name": "John Doe",
//         "last_name": "Doe",
//         "first_name": "John",
//         "email": "john@example.com",
//         "image": "https://example.com/photo.jpg",
//         "uri": "https://plus.google.com/1aeb832ae4d6"
//       }
//   }
// }


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

Расширенный доступ к данным пользователя



Для случаев, когда информации профиля пользователя не достаточно или требуется доступ к API провайдера, Standalone Authentication API обеспечивает унифицированный интерфейс для работы с провайдерами.

Схема взаимодействия приложения с сервисом



// Перенаправление пользователя на страницу провайдера
window.location.href =
  PolyAuth.authCodeURI(REALM_ID, {
    apiv: 'v1',
    key: 'oauth2.google-plus',
    redirectURI: REDIRECT_URI,
    op: 's/token'
  }

// Получение токена доступа
var qs = PolyAuth.QS.parse();

var req =
  PolyAuth
    .api('v1')
    .realm(REALM_ID)
    .auth(qs.key)
    .standaloneToken({code: qs.code, secret: REALM_SECRET});

PolyAuth
    .fetch(req)
    .then(function(resp) {
          console.log(resp);
    });
    
// {
//   "access_token": "eyPae7femio7jo9re4Cimish...",
//   "expires_in": 3575,
//   "id_token": "eyciO6hbGhJd5NiUjIIsImtp...",
//   "token_type": "Bearer"
// }


Запрос на получение токена доступа, управляемого провайдером, должен содержать Realm’s Secret.

Особенностью Standalone Authentication API является то, что профиль пользователя не сохраняется в облаке и приложение получает токен доступа управляемый провайдером (не сервисом) аутентификации.

Аутентификация без ограничений и лимитов



С использованием Standalone Authentication API может быть так же получен и профиль пользователя. При этом токен доступа провайдера не будет разоблачён приложению. Таким образом, может быть достигнута гарантия безопасности персональных данных пользователя даже в не защищённой среде (браузерные и мобильные приложения). Эта функциональность может быть полезна в случаях, когда от социального логина требуется только его базовый функционал.

Схема взаимодействия приложения с сервисом



// Перенаправление пользователя на страницу провайдера
window.location.href =
  PolyAuth.authCodeURI(REALM_ID, {
    apiv: 'v1',
    key: 'oauth2.google-plus',
    redirectURI: REDIRECT_URI,
    op: 's/profile'
  }

// Получение профиля пользователя
var qs = PolyAuth.QS.parse();

var req =
  PolyAuth
    .api('v1')
    .realm(REALM_ID)
    .auth(qs.key)
    .standaloneProfile({code: qs.code});

PolyAuth
    .fetch(req)
    .then(function(resp) {
          console.log(resp);
    });
    
// {
//   "info": {
//     "gender": "male",
//     "name": "John Doe",
//     "last_name": "Doe",
//     "first_name": "John",
//     "gender": "male",
//     "email": "john@example.com",
//     "image": "https://example.com/photo.jpg",
//     "uri": "https://plus.google.com/1aeb832ae4d6"
//   },
//   "uid": "106276572039433743690"
// }
Only registered users can participate in poll. Log in, please.
О подходе, аутентификации как сервиса
21.98% уже использую веб-сервис для аутентификации пользователей 20
38.46% возможно буду использовать 35
13.19% не использую, достаточно логина и пароля 12
12.09% не использую, моё приложение всё умеет 11
13.19% не использую, моё приложение будет всё уметь 12
1.1% не использую, дорого 1
7.69% не использую, другая причина 7
91 users voted. 60 users abstained.
Only registered users can participate in poll. Log in, please.
О приложениях, над которыми работаете
38.39% мобильные 43
42.86% браузерные (фронтенд) 48
35.71% серверные (бэкенд, CMS) 40
60.71% веб-сервисы (фронтенд + бэкенд) 68
7.14% другой вариант 8
112 users voted. 58 users abstained.
Tags:
Hubs:
+6
Comments 6
Comments Comments 6

Articles