Перейти к основному содержимому

Сервис OAuth 2.0

примечание

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

подсказка

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

предупреждение

Если Вы разрабатываете SPA, мобильное или нативное приложение — убедитесь, что можете обеспечить конфиденциальность Client Secret.

Подробнее о причинах — в документации OAuth.

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

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


Термины и сущности

Чтобы избежать возможной путаницы, определимся с основными терминами и сущностями статьи:

  • Идентификатор клиента (Client ID) — публичный уникальный идентификатор, под которым клиент известен сервису. Используется для определения принадлежности получаемых сервисом запросов на авторизацию
  • Клиент (Client) — приложение, запрашивающее у сервиса доступ к ресурсу от имени пользователя
  • Код (Code) — код, выдаваемый клиенту для первичной генерации токенов после успешной авторизации пользователя в системе
  • Пользователь (User) — лицо, обладающее правами доступа к ресурсу
  • Принимающая страница (Redirect URI) — собственный ресурс клиента, на который сервис перенаправит пользователя в случае успешной авторизации последнего в системе
  • Разрешение (Scope) — право доступа, регулирующее как возможность взаимодействия с ресурсом, так и способ этого взаимодействия
  • Ресурс (Resource) — объект или набор данных, доступ к которым регулируется политиками безопасности и управления доступом сервиса
  • Секрет (Client secret) — приватный ключ, использующийся для шифрования и проверки подлинности сообщений, передаваемых между сервисом и клиентом
  • Сервис (Service) — сервис-провайдер OAuth 2.0, обеспечивающий регистрацию клиентов, авторизацию пользователей и последующее предоставление доступа к системе
  • Система (System) — сервер, на котором хранятся ресурсы, защищённые сервисом
  • Токен доступа (Access token) — краткосрочный токен, использующийся для авторизации запросов к ресурсам
  • Токен обновления (Refresh token) — долгосрочный токен, использующийся для обновления Токена доступа
  • Учётные данные клиента (Client credentials) — идентификатор клиента и секрет, использующиеся для идентификации запросов от клиента к сервису
  • Учётные данные пользователя (User credentials) — логин и пароль пользователя, под которыми тот известен системе

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


Логика

Для общего понимания работы этого механизма процесс авторизации можно описать следующими шагами:

  1. Пользователь хочет воспользоваться клиентом для доступа к ресурсу
  2. Клиент перенаправляет пользователя к сервису для его авторизации в системе с помощью учётных данных пользователя
  3. Сервис уточняет у пользователя список разрешений, которые тот готов предоставить клиенту
  4. После утверждения списка сервис перенаправляет пользователя на принимающую страницу, приложив к передаваемому вместе с этим ответу код
  5. Клиент повторно, но уже без участия пользователя, обращается к сервису с полученным ранее кодом для получения многоразовых токенов
  6. Сервис возвращает клиенту токены доступа и обновления
  7. Клиент от имени пользователя (точнее, пользователь с помощью клиента) обращается к ресурсам системы, используя полученный токен доступа
    • Истёк срок жизни токена доступа — клиент повторно обращается к сервису с токеном обновления для получения нового токена доступа
    • Истёк срок жизни токена обновления — процесс начинается с самого начала

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

примечание

Несмотря на то, что выдаваемые клиенту токены схожи с теми, которые пользователь может запросить у сервиса самостоятельно, у них всё же есть значительное отличие в сроке жизни токена обновления:

  • Выдаваемый пользователю — 1 год
  • Выдаваемый клиенту — 1 месяц

Срок жизни токена доступа при этом в обоих случаях одинаков и равен 30 минутам.


Реализация

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

Получение учётных данных клиента

Чтобы клиентское приложение могло успешно взаимодействовать с сервисом, ему должны быть присвоены определённые Client ID и Client Secret. В свою очередь, чтобы получить их, приложение нужно зарегистрировать в кабинете разработчика:

  1. Войдите в существующую или создайте новую учётную запись разработчика
  2. Перейдите на страницу Мои приложения и нажмите Добавить
  3. Укажите название своего приложения и Redirect URL
  4. Нажмите Создать

При этом следует учитывать, что:

  • Название приложения может быть любым и нужно лишь для его идентификации в списке
  • В качестве Redirect URL должен быть указан адрес принимающей страницы, на которую браузер перенаправит пользователя после его авторизации и предоставления прав. В зависимости от размещения принимающей страницы можно указать как локальный, так и внешний адрес
  • Адрес должен быть указан полностью, включая префикс протокола соединения
  • Принимающая страница должна быть доступна по протоколу HTTPS. Redirect URL c префиксом http:// будет отброшен сервисом как небезопасный

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

  • Client ID — публичный уникальный идентификатор, под которым приложение известно сервису. Используется для определения принадлежности именно этому приложению получаемых сервисом запросов на авторизацию
  • Client Secret — приватный ключ приложения, использующийся для шифрования и проверки подлинности сообщений, передаваемых между сервисом и приложением

Если Client ID не содержит чувствительной информации и может передаваться публично, раскрытие Client Secret неограниченному кругу лиц (например, при передаче в запросе на получение кода) может привести к компрометации учетных записей пользователей и несанкционированному доступу к защищенным ресурсам.

На случай непреднамеренного раскрытия Client Secret в карточке приложения доступна кнопка Обновить Client Secret, по нажатию на которую сервис сгенерирует новый секрет для того же идентификатора.

Получение кода

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

Запрос

Подробное описание запроса на авторизацию доступно в документации OAuth, поэтому лишь кратко разберём на примере, какие данные сервис ожидает получить от клиента.

Пример GET-запроса на авторизацию
https://oauth.alor.ru/authorize?
client_id=394...6ff
&scope=trades
&response_type=code
&redirect_uri=https://example.com/callback
&state=rtq...gew

Где:

  • https://oauth.alor.ru — адрес сервиса авторизации для боевого контура системы
  • client_id — полученный при регистрации приложения идентификатор
  • scope — разрешения на доступ к определённым группам ресурсов системы. Если требуется указать несколько разрешений, перечислите их через пробел (scope=trades ordersread personal)
  • response_type — запрашиваемый объект. Принимает лишь одно из двух значений: code и token. Используйте code
  • redirect_uri — адрес принимающей страницы, на которую сервис должен будет перенаправить пользователя вместе с запрошенным кодом после успешной авторизации
  • state — генерируемый клиентом идентификатор соединения, который сервер вернёт неизменным
подсказка

Запрос также может содержать параметр client_secret, в котором передаётся полученный при регистрации приложения секрет. Тем не менее, не рекомендуется передавать его при получении кода в SPA, нативных и мобильных приложениях, так как в этих случаях секрет передаётся в открытом для пользователя виде и его утечка приведёт к компрометации приложения.

Несмотря на то, что в документации OAuth параметр scope назван опциональным, в случае с рассматриваемым OAuth-сервисом разрешения обязательны для заполнения.

  • OrdersRead — чтение ранее выставленных заявок
  • OrdersCreate — выставление, изменение и снятие заявок
  • Trades — чтение совершённых пользователем сделок
  • Personal — чтение персональной информация пользователя: ФИО, почты и т.п.
  • Stats — чтение статистических данных пользователя: прибыль, средние цены и т.п.
подсказка

Запрошенные в scope разрешения могут быть отклонены пользователем на этапе авторизации, в результате чего, например, из запрошенных ordersread orderscreate trades приложение получит только trades. Следует учитывать эту возможность и предусмотреть обработку отличных от запрошенного вариантов.

примечание

Сервис не поддерживает PKCE, в связи с чем описанные в документации OAuth параметры запроса code_challenge и code_challenge_mode будут отброшены при получении.

Ответ

Подробное описание ответа на запрос также доступно в документации OAuth, поэтому здесь вновь лишь пример ответа.

Пример ответа с кодом
https://example.com/callback?
code=eyJ...xPCg
&state=rtq...gew

Где:

  • code — нужный для генерации токенов код
  • state — переданный ранее идентификатор соединения

Если state не был задан в запросе, ответ всё равно будет содержать это поле, но его значение будет undefined.

Получение токенов

Полученный ранее код используется для создания токенов доступа и обновления.

Запрос

Описание запроса доступно в документации OAuth.

Для получения токенов от OAuth-сервиса, выполните POST-запрос с URL https://oauth.alor.ru/token (адрес боевого контура), передав все необходимые значения в теле запроса, закодированные как application/x-www-form-urlencoded.

Пример POST-запроса на получение токенов
grant_type=authorization_code
&code=eyJ...xPCg
&redirect_uri=https://example.com/callback
&client_id=394...6ff
&client_secret=SjO...pRM

Где:

  • grant_type — запрашиваемый тип доступа (всегда authorization_code)
  • code — полученный ранее код
  • redirect_uri — адрес принимающей страницы
  • client_id — публичный уникальный идентификатор клиента
  • client_secret — приватный ключ клиента
подсказка

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

примечание

Сервис не поддерживает PKCE, в связи с чем параметр запроса code_verifier будет отброшен при получении.

Ответ

При успешной обработке запроса сервис вернёт в ответ json-объект, содержащий в себе токены и срок их жизни:

Пример ответа с токенами
{
"access_token": "eyJ...sOA",
"refresh_token": "fe5...73d",
"token_type": "bearer",
"expires_in": 1799,
"refresh_token_expires_in": 5183999
}

Где:

  • access_token — токен доступа
  • refresh_token — токен обновления
  • token_type — тип токена
  • expires_in — оставшееся время жизни токена доступа в секундах
  • refresh_token_expires_in — оставшееся время жизни токена обновления в секундах

Обновление токенов

При использовании кода сервис возвращает в одном сообщении оба токена: доступа и обновления. У каждого из них есть свой срок жизни:

  • 30 минут для токена доступа
  • 1 месяц для токена обновления

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

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


Использование токенов

Возможности применения полученных от OAuth-сервиса токенов полностью идентичны получаемым вручную: токен обновления используется для создания токенов доступа, которые в свою очередь используются для авторизации запросов к HTTP, WebSocket и GraphQl интерфейсам.


Тестовый контур

Несмотря на то, что при получении токенов тестового контура вручную пользователь обращается к OAuth-сервису этого контура (https://oauthdev.alor.ru), подключение приложений к нему бессмысленно по ряду причин:

  • В тестовом контуре нельзя зарегистрировать приложение, что делает невозможным получение собственных Client ID и Client Secret
  • Из-за невозможности регистрации приложения нельзя указать собственный Redirect URI, в связи с чем
  • Для авторизации пользователей в тестовом контуре используются соответствующие учётные записи
  • Шаги с генерацией кода и его последующим использованием для создания токенов выполняются без участия клиента, в связи с чем пользователь сразу после авторизации получает токены

Таким образом, пусть OAuth-сервис и существует в тестовом контуре, приложения могут обращаться к нему только с неким общим Client ID и не могут получить какие-либо сообщения после авторизации пользователя.


Примеры приложений

В качестве примеров, способных помочь во внедрении OAuth 2.0 в Ваше приложение, можем выделить следующие варианты: