↩️ «Выйди и снова зайди, только правильно». Всё ли вы знаете об OAuth 2.0?
Благодаря открытому протоколу OAuth, необязательно заводить для каждой сайта отдельные логин и пароль – можно авторизоваться через Google, Facebook или другой ресурс. Рассказываем, как устроен под капотом протокол OAuth 2.0.
Социальные сети, потоковая передача контента, воркспейсы – везде мы заходим через учетные записи, которые могут содержать личную информацию. Изолированные приложения становятся взаимосвязанными: Twitter позволяет новостным сайтам твитить напрямую, Discord ищет предполагаемых друзей на Facebook, а Jira создает учетки с помощью профилей Github.
Раньше для авторизации сайты и приложения использовали простую схему логин/пароль. Это существенно усложняло задачу взаимодействия приложений: чтобы позволить приложению получить доступ к данным другого приложения, требовалось передать учетные данные. Но это порождало множество проблем, связанных с небезопасным хранением учетных данных и получением неограниченного доступа. Для обеспечения делегированного доступа был создан открытый протокол авторизации OAuth.
Терминология OAuth
Разберем несколько общих терминов. Для упрощения под OAuth будем подразумевать OAuth 2.0.
- Владелец ресурса (
Resource Owner
) – объект, предоставляющий доступ к защищенным ресурсам. - Ресурсный сервер (
Resource Server
) – сервер, на котором размещаются защищенные ресурсы и обрабатываются запросы на доступ. - Клиент (
Client
) – приложение, которое хочет получить доступ к ресурсному серверу и выполнять действия от имени владельца ресурса. Конфиденциальным клиентам (серверные приложения) можно доверять надежное хранение токена, необходимого для доступа к ресурсам, а публичным (мобильные и JS-приложения) – нельзя. - Сервер авторизации (
Authorization Server
) – сервер, который знает владельца ресурса и может авторизовать клиента для доступа к ресурсному серверу.
Функционирование протокола OAuth
OAuth создан для
предоставления сторонним приложениям ограниченного доступа к защищенным
ресурсам без риска для данных пользователя. Это похоже на то, как работает режим
Valet Mode
в Tesla. Этот режим владелец может выставить, если, к примеру, передает машину в сервис. Компьютер автомобиля понимает, что необходимо работать с урезанной функциональностью: ограничить максимальную скорость и ускорение, блокировать багажник и бардачок.
В том же ключе OAuth используется в социальных сетях. Например, при авторизации в Spotify через Facebook приложение Spotify получает доступ лишь к ограниченному набору данных.
При выводе всплывающего окна OAuth работает в фоновом режиме (Рис. 2):
- Spotify отправляет Бобу сообщение с запросом доступа к его публичному профилю, друзьям, почте и т. д.
- Боб разрешает Spotify сбор указанных данных.
- Spotify отправляет ответ в API Facebook.
- Facebook API проверяет присланный ответ и возвращает Spotify токен для доступа к защищенным ресурсам.
- Spotify высылает токен на другой API Facebook, предоставленный сервером авторизации.
- Facebook API отправляет запрошенные данные в Spotify.
Заглянем под капот OAuth
Выше мы обсудили абстрактный дизайн OAuth. Внутри этой системы существуют также области и токены, разрешения и потоки. Разберемся детальнее.
Области и токены OAuth
Области и токены OAuth реализуют детализированное управление доступом. Похоже на киносеанс: область – название фильма, который вы имеете право смотреть, токен – билет, что может проверить лишь сотрудник конкретного кинотеатра.
Вернемся к Рис. 2. Сервер авторизации имеет API, отличающийся от ресурсного сервера. Сервер авторизации служит для проверки и авторизации клиента, в то время как сервер ресурсов хранит запрашиваемые ресурсы. Чтобы ресурсный сервер знал, следует ли выполнять запрос на получение информации, он должен знать, авторизован ли запрашивающий. Тут и появляется токен, чтобы сообщить серверу ресурсов, что запрашивающий был проверен сервером авторизации и имеет разрешение на выполнение запроса. При использовании токенов в качестве прокси-сервера необходимость предоставления учетных данных отпадает. Данные маркеры зашифрованы, но при декодировании сервером ресурсов из них можно вытащить значение области.
Условно можно выделить четыре типа областей:
- доступ для чтения;
- доступ на запись;
- доступ для чтения и записи;
- без доступа.
Определение области действия – мощный инструмент для определения того, какой уровень допуска к пользовательским данным разрешен третьим лицам. Чтобы понять, как это можно использовать, прочитайте документацию Slack и Google, которые демонстрируют различные вариации параметров настройки.
Существует еще один тип токенов – обновляемый (refresh tokens), который используется для автоматического получения нового экземпляра, когда старый больше не функционируют (expired). Такие приложения, как Facebook, могут обеспечить ещё бóльшую степень защиты, периодически проверяя авторизацию с помощью принудительного использования дополнительных refresh-токенов для получения access-токенов. Refresh tokens имеют важную особенность: они могут быть отозваны путем их аннулирования и возврата клиентского доступа к привилегированным ресурсам.
Разрешения и потоки OAuth
Возвращаясь к аналогии с кинотеатром, есть два способа получить билет: покупка в кинотеатре и покупка онлайн. Выбранный метод влияет на последовательнось действий для получения билета. Покупка в театре выглядит так:
- приехать к кинотеатру;
- войти в него;
- пройти к кассе;
- найти сеанс;
- пообщаться с сотрудником кассы;
- оплатить;
- получить билет.
Покупка онлайн:
- перейти на сайт театра;
- найти сеанс;
- добавить билет в заказ;
- оплатить;
- получить билет на e-mail.
Разрешения (grants) диктуют клиенту порядок операций по получению access-токена. Этот уникальный порядок называется потоком.
Вся коммуникация между владельцем ресурса, клиентом и сервером авторизации происходит через строки запроса с параметрами. В этих параметрах содержится информация, необходимая серверу авторизации для понимания того, какому потоку следовать:
- Код разрешения авторизации (Authorization Code Grant) – наиболее распространенный тип разрешений (Рис. 4). Клиент получает уникальный код, выданный сервером авторизации, который затем обменивается на токен.
- Код разрешения авторизации с PKCE – этот вариант используется для публичных клиентов, которым нельзя доверять хранение учетных данных. Используя расширение PKCE (Public Key for Code Exchange), клиент и сервер обмениваются хэшем, чтобы убедиться, что связь не скомпрометирована.
- Учетные данные клиента – иногда клиенты запрашивают доступ для себя, а не для владельца ресурса. Эти экземпляры используют внутренние службы, которым требуется доступ к облачному хранилищу. В этом случае клиент сделает запрос, включающий
client_id
иclient_secret
, которые сервер авторизации проверяет для выдачи access-токенов. Этот тип разрешений должен использоваться только с конфиденциальными клиентами. - Код устройства – используется для устройств, подключенных к интернету, которые не имеют браузеров или снабжены неудобными виртуальными клавиатурами, например, игровая консоль или Smart TV.
Пример: GitHub SSO
Изучим описанные концепции на примере. Teleport – опенсорсный инструмент удаленного доступа, позволяющий юзерам входить в систему через Github single sign-on (SSO) с использованием OAuth. Действующие лица:
Client
: Teleport.Resource Owner
: пользователь Teleport.Authorization Server
: сервер авторизации Github (GAS
).Resource Server
: ресурсный сервер Github (GRS
).
Рассмотрим поток шаг за шагом.
Шаг 1. Пользователь Teleport получает доступ к приложению Teleport.
Шаг 2. Приложение предлагает пользователю Teleport войти с помощью Github SSO.
Шаг 3. Пользователь Teleport нажимает «Войти» и перенаправляется на другую страницу со своими параметрами, передаваемыми в HTTPS GET запросе:
authorization_server
– URL-адрес, обработанный GAS. Для GitHub этоhttps://github.com/login/oauth/authorize
response_type=code
– оповещаетGAS
, что Teleport ожидает код авторизацииclient_id
– передаетGAS
строку, которую он может проверить по реестру авторизованных клиентов. В коде ниже это12345
.redirect_uri
– сообщаетGAS
, на какой URL направить юзера со всеми переменными. Здесь используется следующий:https://teleport.example.com:3080/v1/webapi/github/callback
scope
– определяет ограничения доступа к ресурсамstate
– случайно генерируемая Teleport строка для идентификации клиента и сервера авторизации (в примере используетсяSyl
)
Собрав воедино все, получим следующую строку приглашения:
https://github.com/login/oauth/authorize?response_type=code&client_id=12345&redirect_uri=https://teleport.example.com:3080/v1/webapi/github/callback&scope=read:org&state=syl
Шаг 4. Как только GAS
получит запрос, он проверит client_id
в реестре.
Зная, что Teleport ожидает код авторизации, GAS
отправит пользователя обратно
на URL-адрес с переданными параметрами:
Шаг 5. После получения кода
Teleport автоматически попросит GAS
обменять код на токен с параметрами code
,
redirect_uri
и client_id
. Для обмена используется POST-запрос:
Шаг 6. Используя client_secret
и code
, сервер авторизации может проверить запрос клиента Teleport и выдать токен, в который зашивается область и время жизни:
Шаг 7. Теперь, когда маркер получен, делаем запрос к API от имени пользователя Teleport и получаем желаемое:
Шаг 8. Наконец, GitHub API пропускает юзера.
Заключение
Несмотря на часто упускаемое из виду удобство, OAuth-это сложный протокол, реализация которого потребует времени. Пример, который мы рассмотрели выше – один из сотен вариантов того, как может выглядеть поток OAuth.
Мне нужно оперативно погрузиться во фронтенд. Какой вариант самый быстрый и качественный?
Если 15 лет назад для того, чтобы называть себя фронтенд-разработчиком достаточно было знать HTML, CSS и JavaScript, то сейчас фронтенд-разработка почти не отстает от бэкенд-разработки по количеству фреймворков и сложности стеков. Самый быстрый и качественный вариант — получить знания из первых рук от преподавателей со стажем. Поэтому мы запустили курс «Frontend Basic: принцип работы современного веба», на котором вы:
- освоите стек технологий, который позволит начать работать в любой компании на любом проекте;
- сверстаете свой первый адаптивный макет с учетом семантики и множества декоративных элементов на HTML и CSS;
- поймете, как с помощью JavaScript разрабатывать пользовательские интерфейсы;
- разберетесь, как JavaScript используется в работе с backend и создадите свой первый обмен данными сервером;
- углубитесь в более сложную разработку на React.js и напишете свой интернет-магазин;
- изучите основные команды для работы с GIT, важнейшего инструмента для работы в любой команде.