Типы грантов OAuth
Что такое тип гранта OAuth?
Тип гранта OAuth определяет точную последовательность шагов, входящих в процесс OAuth. Тип гранта также влияет на то, как клиентское приложение взаимодействует с сервисом OAuth на каждом этапе, включая способ передачи самого токена доступа. По этой причине типы грантов часто называют потоками OAuth (OAuth flows).
Сервис OAuth должен быть сконфигурирован с поддержкой конкретного типа гранта до того, как клиентское приложение сможет инициировать соответствующий поток. Клиентское приложение указывает, какой тип гранта оно хочет использовать, в начальном запросе авторизации, который отправляет сервису OAuth.
Существует несколько разных типов грантов с различной сложностью и требованиями к безопасности. Мы сосредоточимся на authorization code и implicit, поскольку они наиболее распространены.
Scopes в OAuth
Для любого типа гранта OAuth клиентское приложение должно указать, к каким данным оно хочет получить доступ и какие операции хочет выполнять. Для этого используется параметр scope в запросе авторизации, отправляемом сервису OAuth.
В базовом OAuth набор доступных областей, к которым клиентское приложение может запросить доступ, уникален для каждого сервиса OAuth. Поскольку имя области — произвольная текстовая строка, формат может сильно различаться у разных провайдеров. Некоторые даже используют полный URI в качестве имени области, аналогично конечной точке REST API. Например, при запросе доступа только на чтение к списку контактов пользователя имя области может принимать любую из следующих форм в зависимости от используемого сервиса OAuth:
scope=contacts
scope=contacts.read
scope=contact-list-r
scope=https://oauth-authorization-server.com/auth/scopes/user/contacts.readonlyКогда OAuth используется для аутентификации, вместо этого часто применяются стандартизованные области OpenID Connect. Например, область openid profile предоставит клиентскому приложению доступ на чтение к предопределённому набору базовой информации о пользователе, такой как его адрес электронной почты, имя пользователя и т.п. Подробнее об этом в разделе OpenID Connect.
Тип гранта authorization code
Тип гранта authorization code поначалу выглядит довольно сложным, но на самом деле он проще, чем кажется, после знакомства с основами.
Коротко: клиентское приложение и сервис OAuth сначала используют перенаправления, чтобы обменяться серией браузерных HTTP‑запросов и инициировать поток. Пользователю предлагается дать согласие на запрошенный доступ. Если он соглашается, клиентскому приложению выдаётся authorization code. Затем клиентское приложение обменивает этот код с сервисом OAuth на access token, который можно использовать для вызовов API и получения соответствующих пользовательских данных.
Вся коммуникация, начиная с обмена кодом/токеном, происходит между серверами по защищённому каналу, и поэтому невидима для конечного пользователя. Этот защищённый канал устанавливается при первоначальной регистрации клиентского приложения в сервисе OAuth. В это время также генерируется client_secret, который клиентское приложение должно использовать для аутентификации при отправке таких межсерверных запросов.
Поскольку самые чувствительные данные (токен доступа и пользовательские данные) не передаются через браузер, этот тип гранта, вероятно, самый безопасный. Серверные приложения по возможности всегда должны использовать именно его.

1. Запрос авторизации
Клиентское приложение отправляет запрос к конечной точке /authorization сервиса OAuth с просьбой о доступе к определённым пользовательским данным. Обратите внимание, что сопоставление конечных точек может отличаться у разных провайдеров — в лабораторных для этой цели используется конечная точка /auth. Однако вы всегда сможете распознать её по параметрам в запросе.
Этот запрос обычно содержит в строке запроса следующие важные параметры:
client_id- Обязательный параметр, содержащий уникальный идентификатор клиентского приложения. Это значение генерируется при регистрации клиентского приложения в сервисе OAuth.redirect_uri- URI, на который браузер пользователя должен быть перенаправлен при отправке кода авторизации клиентскому приложению. Это также callback URI. Многие атаки на OAuth основаны на эксплуатации изъянов в валидации этого параметра.response_type- Определяет, какого типа ответ ожидает клиентское приложение, а значит, какой поток оно хочет инициировать. Для типа гранта authorization code значение должно бытьcode.scope- Используется для указания подмножества пользовательских данных, к которым клиентское приложение хочет получить доступ. Обратите внимание, что это могут быть как кастомные области, определённые провайдером OAuth, так и стандартизованные области OpenID Connect. Подробнее об OpenID Connect.state- Хранит уникальное, непредсказуемое значение, привязанное к текущей сессии на стороне клиентского приложения. Сервис OAuth должен вернуть это точное значение в ответе вместе с кодом авторизации. Этот параметр служит формой CSRF‑токена для клиентского приложения, гарантируя, что запрос к его конечной точке/callbackисходит от того же пользователя, который инициировал поток OAuth.
2. Вход пользователя и согласие
Получив начальный запрос, сервер авторизации перенаправит пользователя на страницу входа, где его попросят войти в аккаунт у провайдера OAuth (часто — в аккаунт социальной сети).
Затем пользователю покажут перечень данных, к которым клиентское приложение запрашивает доступ. Он формируется на основе scope, указанного в запросе авторизации. Пользователь может согласиться или отказаться.
Важно: после того как пользователь одобрил определённую область для данного клиентского приложения, этот шаг в дальнейшем будет проходить автоматически, пока у пользователя есть действительная сессия с сервисом OAuth. Иными словами, при первом выборе «Войти через соцсеть» ему придётся вручную войти и дать согласие, но при последующих посещениях он часто сможет войти одним кликом.
3. Выдача кода авторизации
Если пользователь дал согласие, его браузер будет перенаправлен на конечную точку /callback, указанную в параметре redirect_uri запроса авторизации. Результирующий GET запрос будет содержать код авторизации в параметре строки запроса. В зависимости от конфигурации он также может включать параметр state с тем же значением, что и в запросе авторизации.
4. Запрос токена доступа
Получив код авторизации, клиентское приложение должно обменять его на токен доступа. Для этого оно отправляет POST запрос к конечной точке /token сервиса OAuth. С этого момента вся коммуникация идёт по защищённому межсерверному каналу и, как правило, не может наблюдаться или контролироваться атакующим.
Помимо client_id и кода авторизации, обратите внимание на новые параметры:
client_secret- Клиентское приложение должно аутентифицировать себя, включив секретный ключ, выданный при регистрации в сервисе OAuth.grant_type- Нужен, чтобы новая конечная точка понимала, какой тип гранта хочет использовать клиентское приложение. В данном случае значение должно бытьauthorization_code.
5. Выдача токена доступа
Сервис OAuth валидирует запрос на получение токена доступа. Если всё корректно, сервер отвечает, выдавая клиентскому приложению токен доступа с запрошенной областью.
6. Вызов API
Теперь у клиентского приложения есть токен доступа, и оно может получить пользовательские данные с сервера ресурсов. Для этого выполняется вызов API к конечной точке /userinfo сервиса OAuth. Токен доступа передаётся в заголовке Authorization: Bearer, чтобы подтвердить право доступа к этим данным.
7. Выдача ресурса
Сервер ресурсов должен проверить, что токен действителен и принадлежит текущему клиентскому приложению. Если да, он отвечает, отправляя запрошенный ресурс — то есть пользовательские данные в соответствии с областью токена доступа.
Клиентское приложение наконец может использовать эти данные по назначению. В случае аутентификации OAuth они обычно используются как идентификатор для выдачи пользователю аутентифицированной сессии, то есть для входа.
Тип гранта Implicit
Тип гранта implicit гораздо проще. Вместо получения кода авторизации и последующего обмена его на токен доступа клиентское приложение получает токен доступа сразу после того, как пользователь дал согласие.
Почему бы клиентским приложениям не использовать всегда implicit? Ответ прост — он гораздо менее безопасен. При использовании implicit весь обмен происходит через браузерные перенаправления, защищённого межсерверного канала, как в потоке authorization code, нет. Это означает, что чувствительный токен доступа и пользовательские данные более подвержены потенциальным атакам.
Тип гранта implicit больше подходит для одностраничных приложений (SPA) и нативных десктопных приложений, которые не могут легко хранить client_secret на бэкенде и, следовательно, получают меньше преимуществ от использования authorization code.

1. Запрос авторизации
поток Implicit начинается почти так же, как authorization code. Единственное существенное отличие — параметр response_type должен быть установлен в token
2. Вход пользователя и согласие
Пользователь входит и решает, давать ли согласие на запрошенные разрешения. Этот процесс идентичен потоку authorization code.
3. Выдача токена доступа
Если пользователь дал согласие, далее начинается различие. Сервис OAuth перенаправит браузер пользователя на redirect_uri, указанный в запросе авторизации. Однако вместо передачи кода авторизации в параметре строки запроса он отправит токен доступа и другие связанные данные во фрагменте URL.
Поскольку токен доступа передаётся во фрагменте URL, он никогда не отправляется напрямую на сервер клиентского приложения. Вместо этого клиентскому приложению нужен подходящий скрипт, чтобы извлечь фрагмент и сохранить его.
4. Вызов API
Как только клиентское приложение успешно извлечёт токен доступа из фрагмента URL, оно может использовать его для вызовов API к конечной точке /userinfo сервиса OAuth. В отличие от потока authorization code, это также происходит через браузер.
5. Выдача ресурса
Сервер ресурсов должен проверить, что токен действителен и принадлежит текущему клиентскому приложению. Если да, он отвечает, отправляя запрошенный ресурс, то есть пользовательские данные на основе области, связанной с токеном доступа.
Клиентское приложение может использовать эти данные по назначению. В случае аутентификации OAuth они обычно используются как идентификатор для выдачи пользователю аутентифицированной сессии, то есть для входа.
Last updated