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

Сервис 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 в Ваше приложение, можем выделить следующие варианты: