Аутентификация и авторизация, OpenID и OAuth

Аутентификация

Аутентификация — процедура проверки подлинности. Необходимо удостовериться что пользователь тот, за кого себя выдает. В интернете обычная процедура аутентификации состоит из ввода логина и пароля пользователя. Общий вид аутентификации показан на рисунке ниже.

Аутентификация

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

Авторизация

Иногда аутентификации бывает достаточно, чтобы получить проверить что пользователь тот, за кого себя выдает (он знает секретную фразу — пароль).

Второй шаг при проверке пользовательского доступа — авторизация. Авторизация это предоставление определенному лицу или группе лиц прав на доступ к определенным действиям. Например доступ в часть к публичной части сайта дается всем. Доступ в личный кабинет выдается только аутентифицированным пользователь. А доступ к части администрирования — только авторизованным пользователям с соответствующими правами.

Таким образом, аутентификация это проверка подлинности данных. Авторизация проверка прав доступа. Обычно авторизация состоит из 2 шагов:

  1. Убедиться, что поступающий запрос аутентифицирован
  2. Убедиться, что пользователь имеет права к запрашиваемому ресурсу.

Авторизация

В некоторых случаях выполняются оба действия за один шаг. Последние несколько лет получили распространение другие системы аутентификации. Есть ли способ узнать пользователей, которые не зарегистрированы в нашей системе? В таком случае прибегают к 3-й стороне. Система A спрашивает у системы B проверку подлинности пользователя, в случае успешной проверки система A предполагает что пользователь является известным. Эта концепция называется «Federated Identity«. Популярные сервисы уже реализовали поддержку этой технологии.

Federated Identity

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

Основной FlowChart Federated Identity показан ниже

Federated Identity

Почему использовать Federated Identity?

  1. Не требуется разрабатывать и поддерживать модуль управления пользователями. Это несколько компонент (вход, регистрация, изменение пароля, «забыли пароль», полики безопасности и др.).
  2. Использовать большую базу уже зарегистрированных пользователей. Есть очень много систем и приложений, где зарегистрировано большинство пользователей. У всех есть как минимум электронная почта.
  3. Профили пользователей могут быть одинаковыми для нескольких систем. Поддерживать актуальность во всех приложениях люди не будут, а следить за свежестью данных в основной используемой системе — как минимум необходимо.

Какие бывают протоколы Federated Identity? Основные используемые сегодня это OpenID и OAuth.

OpenID

OpenID — это открытая децентрализованная система, которая позволяет пользователю использовать одну учетную запись для аутентификации в различных системах. При этом эти системы не обязательно должны быть связаны друг с другом. Начала свое развитие в 2005 году, одним из создателей LiveJournal.

Существует 3 важных понятия в OpenID аутентификации:

  1. User — пользователь, который делает запрос на аутентификацию
  2. Provider — система, которая хранит данные пользователя, и обрабатывает запросы OpenID
  3. RelyingParty — зависимая сторона, которая хочет проверить подлинность пользователя.

Процесс аутентификации по OpenID описывается следующими шагами:

  1. Пользователь пытается получить доступ к закрытому ресурсу зависимой стороны (Relying Party);
  2. Зависимая сторона запрашивает у пользователя логин;
  3. Пользователь отправляет свой URL OpenID;
  4. Зависимая сторона перенаправляет пользователя к провайдеру OpenID для проверки подлинности;
  5. Пользователь вводит свои данные для входа;
  6. Провайдер OpenID аутентифицирует пользователя;
  7. В случае успешной аутентификации, провайдер перенаправляет пользователя обратно к зависимой стороне, включая идентификационную информацию;
  8. Зависимая сторона проверяет токен от провайдера и допускает пользователя.

OAuth

OAuth — протокол, который позволяет авторизовывать (в отличии от OpenID) пользователя в конкретной системе. После авторизации приложение может делать запросы от имени пользователя. OAuth позволяет нам поделиться ресурсами с известными провайдерами. Аналогично как и в OpenID, OAuth также содержит 3 важных понятия:

  1. User — пользователь, который делает запрос;
  2. Provider — система, которая содержит информацию о пользователе и предоставляет API для доступа к ним;
  3. Consumer — Потребитель, это 3-я сторона, которая запрашивает у пользователя разрешение на доступ к информации, чтобы получить возможность делать запросы от имени пользователя.

Workflow имеет следующий вид:

  1. Пользователь (User) пытается получить закрытую информацию от Потребителя;
  2. Потребитель запрашивает у пользователя разрешение поделиться некоторой информацией о нем (зависит от выбранных прав доступа, scope);
  3. Пользователь выбирает своего провайдера;
  4. Потребитель должен знать API провайдера, обычно Потребитель зарегистрирован у провайдера и имеет свой ключ
  5. Потребитель перенаправляет к провайдеру со своим ключем (consumer_token) и списком возможностей (scope), которые хочет потребитель иметь;
  6. Пользователь разрешает доступ приложениею с выбранными возможностями и предоставляет доступ к некоторым своим ресурсам (именно ресурсам в системе провайдера);
  7. Провайдер создает токен (token) и перенаправляет обратно к потребителю;
  8. Потребитель расширяет токен информацией о себе, чтобы получить access_token конкретного пользователя, привязанного к конкретному потребителю;
  9. Потребитель использует полученный access_token, чтобы авторизовать запрос к провайдеру и спросить немного информации о пользователе;
  10. Провайдер отсылает эту информацию потребителю;
  11. Потребитель проверяет информацию и авторизует пользователя.

OpenID vs OAuth

  1. Из названий видно, OpenID обеспечивает проверку подлинности пользователя, в то время как OAuth обеспечивает авторизацию;
  2. В OpenID пользователь может ввести свою информацию для доступа на стороне потребителя;
  3. OpenID — децентрализован, в то время как OAuth привязан к конкретному провайдеру;
  4. В случае OpenID проверяющая сторона не известна поставщику, но в OAuth провайдер знает все о поставщике;
  5. В обоих случаях пользователь вводит свои данные для входа на стороне провайдера.

Понятное дело, что обе системы OpenID и OAuth имеют свои достоинства и недостатки. Однако возможности OAuth привлекают меня больше.

Построение системы OAuth

Один раз реализовывал свою систему OAuth. Если есть задача развернуть промышленную систему OAuth — лучше использовать готовые библиотеки. Для того, чтобы понять как это работает или решить узкую задачу можно воспользоваться схемой ниже.

Построение OAuth

 

В этом примере 3 действующих лица.

  1. Потребитель, который хочет получить данные от провайдера
  2. Web, который работает на первом этапе с потребителем
  3. API, который работает с уже авторизованным потребителем.

Схема работы

  1. Потребитель запрашивает у провайдера данные о пользователе;
  2. Т.к. потребитель не авторизован, провайдер перенаправляет потребителя на страницу авторизации и передает AppID + адрес, куда вернуть пользователя после авторизации;
  3. В Web части провайдера пользователь вводит свой логин и пароль (в этом время сам провайдер аутентифицирует и авторизует пользователя). Далее провайдер проверяет информацию о приложении по AppID. Если все верно возвращает потребителю code для получения access_token.
    На схеме сплошными линиями изображены запросы, которые пользователь будет видеть в браузере, а пунктирными — запросы от системы потребителя напрямую к провайдеру (например с сервера, где расположено приложение потребителя);
  4. Потребитель запрашивает AccessToken, передав провайдеру code, полученный ранее. При этом стоит учитывать, что code имеет свой срок жизни, также как и AccessToken;
  5. Провайдер проверяет code и возвращает действительный AccessToken;
  6. Потребитель делает запросы, добавляя в каждый запрос AccessToken, а провайдер выполняет эти запросы, проверяя действителен ли AccessToken.