Что такое OAuth?
Jinhua Luo
November 18, 2022
Создание новых учетных записей для различных веб-сайтов всегда было проблематичным. Большинство из них — это избыточная работа, так как они содержат одну и ту же информацию о пользователе, такую как имя и номер телефона.
«Возможно ли разрешить приложению доступ к моим данным, не передавая ему пароль?»
OAuth — это стандарт, который пытается решить эту проблему, предоставляя централизованную авторизацию.
OAuth, что означает «Открытая авторизация», — это открытый стандарт для делегирования доступа. Он позволяет вам (владельцам ресурсов) делиться информацией между приложениями и веб-сайтами, не раскрывая свои пароли. Он широко используется, и вы, вероятно, ежедневно пользуетесь услугами OAuth. Например, чтобы войти на GeeksforGeek, вы можете выбрать вход с помощью вашей учетной записи Google. Таким образом, вы разрешаете GeeksforGeek доступ к некоторой информации в вашей учетной записи Google, такой как имя пользователя, фотография профиля и т.д.

История OAuth
Протокол OAuth 1.0 был опубликован как RFC 5849, информационный запрос на комментарии, в апреле 2010 года.
Протокол OAuth 2.0 был опубликован как RFC 6749, а использование токенов-носителей OAuth 2.0 было опубликовано как RFC 6750, в октябре 2012 года.
Хотя OAuth 2.0 был построен на основе опыта внедрения OAuth 1.0, это полная переработка OAuth 1.0 с нуля, сохраняющая только общие цели и пользовательский опыт. OAuth 2.0 не совместим с OAuth 1.0.
Как работает OAuth 2.0
В протоколе OAuth вместо использования имени пользователя и пароля владельца ресурса для доступа к защищенным ресурсам, клиент использует токен доступа. Клиент получает токен доступа от сервера авторизации после одобрения владельца ресурса. Чтобы владелец ресурса мог предоставить авторизацию клиенту, он сначала должен быть аутентифицирован в приложении. И поскольку аутентификация происходила только между владельцем ресурса и приложением, сторонний клиент не может узнать никакой личной информации владельца ресурса.
Мы видим, что реализация протокола OAuth значительно упрощает процесс аутентификации стороннего клиента. Все, что ему нужно сделать, — это получить авторизацию от пользователя, запросить токен доступа, использовать его и получить информацию о пользователе (защищенный ресурс). Это не требует регистрации новых учетных записей или раскрытия учетных данных, что снижает поверхность атаки и повышает безопасность сети.
Стоит отметить, что OAuth — это не аутентификация. Здесь речь идет об авторизации. Пользователь не входит в приложение. Он только разрешает стороннему приложению получить некоторую информацию о себе.
Процесс авторизации OAuth
Роли
OAuth определяет четыре роли:
Клиент — Приложение, которое хочет получить доступ к вашим данным (владельца ресурса) и выполнять запросы к защищенным ресурсам от имени владельца ресурса и с его авторизацией.
Владелец ресурса — Пользователь, который владеет данными на сервере ресурсов, хочет использовать услуги клиента и имеет учетную запись на сервере авторизации. Например, я являюсь владельцем ресурса своего профиля на Facebook и хочу использовать услуги GeeksforGeeks.
Сервер авторизации — Основной механизм OAuth. Выдает токены доступа клиенту после успешной аутентификации владельца ресурса и получения авторизации.
Сервер ресурсов — Сервер, на котором хранятся данные, которые хочет получить клиент, способный принимать и отвечать на запросы к защищенным ресурсам с использованием токенов доступа.
Поток протокола OAuth

Шаг A: Стороннее приложение запрашивает авторизацию у пользователя
Шаг B: Стороннее приложение получает грант авторизации, который является учетными данными, представляющими авторизацию владельца ресурса
Шаг C: Стороннее приложение запрашивает токен доступа, используя грант авторизации
Шаг D: Сервер авторизации аутентифицирует клиента и проверяет грант авторизации, если он действителен, выдает токен доступа стороннему приложению
Шаг E: Стороннее приложение использует токен доступа для запроса защищенных ресурсов у сервера ресурсов
Шаг F: Сервер ресурсов проверяет токен доступа и выполняет запрос, если он действителен
Код авторизации и токен доступа
Существует четыре типа грантов авторизации для получения токенов доступа от серверов авторизации. Мы рассмотрим только метод Authorization Code, так как он является самым безопасным и распространенным.

Шаг A: Стороннее приложение предлагает пользователю выбрать метод авторизации, например GitHub, а затем перенаправляет пользователя на сервер авторизации с параметрами, такими как client_id и redirect_uri
Пример запроса:
GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1 Host: server.example.com
Шаг B: Пользователь входит в систему и авторизуется
Шаг C: Сервер авторизации перенаправляет пользователя обратно на сервер стороннего приложения в соответствии с redirect_uri, предоставляя код авторизации
Пример ответа:
HTTP/1.1 302 Found Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA &state=xyz
Шаг D: Стороннее приложение использует код авторизации для обмена на токен доступа у сервера авторизации
Пример запроса:
POST /token HTTP/1.1 Host: server.example.com Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW Content-Type: application/x-www-form-urlencoded grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
Шаг E: Сервер авторизации проверяет и возвращает токен доступа
Пример ответа от сервера авторизации:
HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache { "access_token":"2YotnFZFEjr1zCsicMWpAA", "token_type":"example", "expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", "example_parameter":"example_value" }
Конкретный пример
Боб хочет красиво распечатать свои заказы на Amazon с помощью программного обеспечения под названием Rabbit.
Владелец ресурса -> Боб
Клиент (стороннее приложение) -> Программное обеспечение Rabbit
Сервер авторизации -> Сервер авторизации Amazon
Сервер ресурсов -> Базы данных Amazon для хранения информации о заказах
Защищенные ресурсы -> Информация о заказах Боба на Amazon

Почему код авторизации и токен доступа должны быть получены отдельно?
Код авторизации и токен доступа получаются отдельно для обеспечения мер безопасности.
В протоколе OAuth2 код авторизации — это временный код, который клиент обменивает на токен доступа. Код получается от сервера авторизации, где пользователь (владелец ресурса) имеет возможность увидеть, какую информацию запрашивает клиент, и одобрить или отклонить запрос.
После успешного входа и авторизации пользователь перенаправляется обратно в приложение с временным кодом авторизации в URL.
Этот код авторизации обычно действителен в течение десяти минут и только один раз. Короткий срок действия снижает риск утечки информации пользователя, если код будет украден. В то время как срок действия access_token относительно длительный, обычно 1-2 часа. Если он будет утечен, это может представлять большую опасность для безопасности данных пользователя.
Кроме того, для обмена на токен доступа клиенту необходимо предоставить client ID и client secret в дополнение к коду авторизации. Сервер авторизации использует эти параметры для аутентификации клиента и проверки того, что запрашивающий токен доступа является доверенным. Если код авторизации будет утечен, но у хакера нет client ID и client secret, он все равно не сможет получить токен доступа. Даже если он каким-то образом получит client ID и client secret, ему все равно придется соревноваться с клиентским сервером, так как код авторизации действителен только один раз. Этот механизм значительно увеличивает сложность потенциальных атак. Если мы пропустим шаг получения кода авторизации и сразу вернем токен доступа, злоумышленник может легко использовать токен доступа для кражи информации пользователя.
OIDC (OpenID Connect)
Какова цель использования OAuth для авторизации? Это получение различной информации о пользователе. Почему бы не стандартизировать вывод, чтобы сторонние приложения могли использовать его напрямую?
OIDC делает эту стандартизацию.
Как OIDC это делает? Проще говоря, он возвращает дополнительный JWT-формат id_token, содержащий основную информацию о пользователе, вместе с access token. Сторонние приложения могут получить информацию о пользователе, проверив алгоритм подписи и верифицировав подпись на id_token с помощью открытого ключа.
Кроме того, OIDC предоставляет конечную точку UserInfo. Сторонние сервисы могут использовать токен доступа для доступа к этой конечной точке и получения дополнительной информации о пользователе.
Еще одна особенность OIDC — это Single Sign On (SSO) и Single Log Out (SLO). SSO улучшает удобство использования, позволяя пользователю иметь аутентифицированные сессии с разными клиентами без необходимости каждый раз вводить учетные данные. Если пользователь успешно вошел в одно приложение, ему не нужно снова вводить пароль при входе в другие приложения.
SLO повышает безопасность, гарантируя, что после инициации единого выхода из системы не останется активных сессий от SSO-сессии. Пользователю нужно выйти только один раз, и все сессии будут завершены, что предотвращает их захват или неправомерное использование.
Стоит отметить, что OIDC не стандартизирует конкретный метод аутентификации, такой как пароли или распознавание лиц. Вместо этого он определяет, как делегировать аутентификацию централизованному провайдеру аутентификации, что мы получаем после аутентификации — id token, как этот токен проверяется — JWT-формат, и какую информацию о пользователе содержит этот id token. Таким образом, сторонним приложениям больше не нужно изобретать велосипед.
Поддержка OAuth/OIDC в APISIX
Apache APISIX — это облачный API-шлюз с открытым исходным кодом. Это динамический, высокопроизводительный API-шлюз, который можно использовать для обработки традиционного трафика север-юг, а также трафика восток-запад между сервисами. Он также может использоваться как контроллер ingress для k8s.
Поскольку APISIX — это API-шлюз, который действует как прокси для нескольких вышестоящих серверов приложений, наиболее естественно разместить централизованную авторизацию и аутентификацию на API-шлюзе.
Плагин OpenID Connect (OIDC) в APISIX поддерживает протокол OpenID Connect. Пользователи могут использовать этот плагин для подключения APISIX ко многим провайдерам идентификации (IdP), таким как Okta, Keycloak, Ory Hydra, Authing и т.д., и развернуть его как централизованный шлюз аутентификации. OIDC является надмножеством OAuth, поэтому этот плагин также поддерживает OAuth.
Схема развертывания:

Пример конфигурации: Интеграция Keycloak для аутентификации с Apache APISIX
Настройка Keycloak
| Параметр | Значение |
|---|---|
| Адрес Keycloak | http://127.0.0.1:8080/ |
| Realm | myrealm |
| Тип клиента | OpenID Connect |
| ID клиента | myclient |
| Секрет клиента | e91CKZQwhxyDqpkP0YFUJBxiXJ0ikJhq |
| URI перенаправления | http://127.0.0.1:9080/anything/callback |
| Discovery | http://127.0.0.1:8080/realms/myrealm/.well-known/openid-configuration |
| URI выхода | /anything/logout |
| Имя пользователя | myuser |
| Пароль | myrealm |
| Realm | mypassword |
Пример кода
curl -XPUT 127.0.0.1:9080/apisix/admin/routes/1 -H "X-API-KEY: edd1c9f034335f136f87ad84b625c8f1" -d '{ "uri":"/anything/*", "plugins": { "openid-connect": { "client_id": "myclient", "client_secret": "e91CKZQwhxyDqpkP0YFUJBxiXJ0ikJhq", "discovery": "http://127.0.0.1:8080/realms/myrealm/.well-known/openid-configuration", "scope": "openid profile", "bearer_only": false, "realm": "myrealm", "redirect_uri": "http://127.0.0.1:9080/anything/callback", "logout_path": "/anything/logout" } }, "upstream":{ "type":"roundrobin", "nodes":{ "httpbin.org:80":1 } } }'
Когда вы посетите http://127.0.0.1:9080/anything/test после успешного создания API, вы будете перенаправлены на страницу входа Keycloak, так как вы еще не вошли в систему:

Введите myuser как имя пользователя и mypassword как пароль, и вы будете перенаправлены на следующую страницу.

Посетите http://127.0.0.1:9080/anything/logout, чтобы выйти из системы:

Итог
Короче говоря, стандарт OAuth — это популярное решение как для приложений, так и для пользователей. Он обеспечивает удобство и безопасность, позволяя пользователям использовать услуги на нескольких платформах без передачи своих учетных данных. Apache APISIX — это популярный API-шлюз, который поддерживает интеграцию с различными провайдерами идентификации (Keycloak, Ory Hydra, Okta, Auth0 и т.д.) для защиты ваших API.
Читайте больше: