Почему в OAuth2 имеется поток «Код авторизации», когда поток «Неявный» работает так хорошо?

264

С потоком «неявного» клиент (вероятно, браузер) получит токен доступа после того, как владелец ресурса (то есть пользователь) предоставил доступ.

Однако с потоком «Код авторизации» клиент (обычно веб-сервер) получает код авторизации только после того, как владелец ресурса (то есть пользователь) предоставил доступ. С этим кодом авторизации клиент затем делает еще один вызов API, передавая client_id и client_secret вместе с кодом авторизации, чтобы получить токен доступа. Все хорошо описано здесь .

Оба потока имеют одинаковый результат: токен доступа. Однако «неявный» поток намного проще.

Вопрос: зачем беспокоиться о потоке «Код авторизации», когда «неявные» швы потока должны быть хорошими? Почему бы не использовать "Implicit" для веб-сервера?

Это больше работы как для поставщика, так и для клиента.

Арон Вуст
источник
4
Проверьте stackoverflow.com/questions/7522831/…
Джон Ниландер
1
Спасибо, прочитайте это уже. Не отвечает на вопрос, хотя.
Арон Вуст
1
Хороший вопрос на самом деле и редко отвечает :) Смотрите ниже.
Николя Гарнье
1
@AronWoost Я думаю, вы неправильно понимаете веб-приложение сервера и приложение браузера
onmyway133
@entropy Это был мой вопрос; почему бы не использовать поток браузера для сервера.
Арон Вуст

Ответы:

294

tl; dr: Это все из соображений безопасности.

OAuth 2.0 хотел соответствовать этим двум критериям:

  1. Вы хотите разрешить разработчикам использовать URI перенаправления не-HTTPS, потому что не у всех разработчиков есть сервер с поддержкой SSL, и если они делают это, он не всегда должным образом настроен (несамостоятельно подписанные, доверенные сертификаты SSL, часы синхронизированного сервера ...).
  2. Вы не хотите, чтобы хакеры могли украсть токены доступа / обновления, перехватывая запросы.

Подробности ниже:

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

В неявном потоке токен доступа передается непосредственно как хеш-фрагмент (не как параметр URL). Одна важная вещь о хеш-фрагменте состоит в том, что, как только вы перейдете по ссылке, содержащей хеш-фрагмент, только браузер узнает о хеш-фрагменте. Браузеры передадут фрагмент хеша непосредственно на целевую веб-страницу (URI перенаправления / веб-страница клиента). Хеш-фрагмент имеет следующие свойства:

  • Они не являются частью HTTP-запроса, поэтому они не могут быть прочитаны серверами и поэтому не могут быть перехвачены промежуточными серверами / маршрутизаторами (это важно).
  • Они существуют только в браузере - на стороне клиента - поэтому единственный способ прочитать фрагмент хеша - использовать JavaScript, который запускается на странице.

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

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

  • Злоумышленник может получить токен доступа от пользователя на другом веб-сайте / в приложении (скажем, если он является владельцем другого веб-сайта / приложения), зарегистрировать токен на своем веб-сайте, а затем передать его в качестве параметра URL-адреса на своем веб-сайте. поэтому выдает себя за пользователя на вашем сайте. Чтобы избежать этого, вам нужно проверить идентификатор клиента, связанный с токеном доступа (например, для Google вы можете использовать конечную точку tokeninfo), чтобы убедиться, что токен был выдан с вашим собственным идентификатором клиента (т.е. вашим собственным приложением) или проверить подпись если вы используете IDToken (но для этого требуется секрет вашего клиента).
  • Если запрос на аутентификацию не был получен из вашего собственного свойства (так называемые атаки фиксации сеанса), во избежание этого вы захотите сгенерировать случайный хеш на своем веб-сайте, сохраните его в файле cookie и передайте тот же хеш в параметре URL состояния запрос на аутентификацию, когда пользователь возвращается, вы проверяете параметр состояния с помощью cookie, и он должен совпадать.

В потоке кода авторизации невозможно передать токен доступа непосредственно в параметре URL, поскольку параметры URL являются частью HTTP-запроса, поэтому любой промежуточный сервер / маршрутизаторы, по которым ваш запрос будет проходить (может быть сотнями), смогут прочитайте маркер доступа, если вы не используете шифрованное соединение (HTTPS), разрешающее так называемые атаки «человек посередине».

Передача токена доступа непосредственно в параметре URL теоретически возможна, но сервер аутентификации должен был бы убедиться, что URI перенаправления использует HTTPS с шифрованием TLS и «доверенный» сертификат SSL (как правило, от несвободного центра сертификации) чтобы убедиться, что целевой сервер является законным и что HTTP-запрос полностью зашифрован. Если все разработчики приобретут SSL-сертификат и правильно настроят SSL в своем домене, это будет огромной проблемой и значительно замедлит их внедрение. Вот почему предоставляется промежуточный одноразовый «код авторизации», который сможет обмениваться только законный получатель (потому что вам нужен секрет клиента), и что этот код будет бесполезен для потенциальных хакеров, перехватывающих запросы по незашифрованным транзакциям (потому что они не

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

Николя Гарнье
источник
12
@AndyDufresne Эти два запроса должны выполняться через HTTPS (обязательно), поскольку они являются запросами к серверу OAuth, который должен поддерживать только HTTPS. Только сервер-клиент / запросчик не должен поддерживать HTTPS, поэтому только Auth Codeпотенциально отправляется в незашифрованном виде по HTTP. Но Auth Codeбесполезно без идентификатора клиента / секрета. По сути, смысл потока OAuth-кода заключается в том, что бремя наличия сервера с поддержкой SSL лежит на провайдере OAuth (Google / Facebook и т. Д.), А не на пользователях API (вы, я).
Николя Гарнье
5
Хорошо, теперь я понимаю, что код авторизации может передаваться по обычному HTTP и может быть подвергнут риску. Сделав код одноразового использования и приняв секрет клиента для обмена на токен доступа, сервер авторизации может предотвратить атаку «Человек посередине». Но это также не относится к токену доступа? Поскольку пользователь API может использовать обычный HTTP, не будет ли риск, что хакер обнаружит токен доступа? PS - Я высоко ценю ваши усилия по объяснению концепции, даже спустя некоторое время, так как эта тема была активной. Спасибо !
Энди Дюфрен
8
no pb :) Запросы к API - то есть, когда токен доступа отправляется по проводной линии (для авторизации запроса) - также обязательно выполняются по HTTPS. Теоретически, клиент никогда не должен отправлять токен доступа по сети в обычном HTTP-режиме.
Николя Гарнье
5
Маркер доступа на этом шаге является частью ответа HTTPS-запроса от Клиента на сервер ресурсов. Этот ответ все еще зашифрован.
Николя Гарнье
13
В основном запросы, которые инициируются от клиента к серверу ресурсов, выполняются через HTTPS (поскольку сервер владельца ресурса должен поддерживать HTTPS). Это только запросы, которые инициируются откуда-то еще к клиенту, которые могут быть выполнены через HTTP (потому что клиентский сервер может не поддерживать HTTPS). Например, перенаправление, которое происходит во время потока авторизации после того, как пользователь предоставляет авторизацию на странице gant, является перенаправлением, инициируемым из браузера на клиентский сервер, и может выполняться в HTTP.
Николя Гарнье
8

Неявная Flow делает весь поток довольно легко, но и менее безопасной .
Поскольку клиентское приложение, обычно выполняемое в браузере на JavaScript, менее надежно, токены обновления для долговременного доступа не возвращаются.
Этот поток следует использовать для приложений, которым требуется временный доступ (несколько часов) к данным пользователя.
Возврат токена доступа клиентам JavaScript также означает, что вашему браузерному приложению необходимо уделить особое внимание - подумайте о XSS-атаках, которые могут привести к утечке токена доступа в другие системы.

https://labs.hybris.com/2012/06/05/oauth2-the-implicit-flow-aka-as-the-client-side-flow

lakesare
источник
Я ожидаю, что если у вас есть уязвимость XSS, то даже поток кода авторизации мало поможет. Но я согласен с тем, что, поскольку способ передачи токена доступа в javascript в неявном потоке стандартизирован (как фрагмент хеша), и если на веб-сайте существует уязвимость XSS, тогда создается атака, которая считывает токен доступа из хэша URL-адреса. фрагмент довольно прост. С другой стороны, при использовании потока кода авторизации возможна подделка межсайтовых запросов.
Марсель
Кроме того, речь идет не только о межсайтовом скриптинге. Любая библиотека JavaScript, работающая на вашем сайте, может попытаться украсть маркер доступа (например, сторонние библиотеки CDN или библиотеки с открытым исходным кодом, которые использует ваша среда JavaScript).
Марсель
2
XSS не является большой проблемой сейчас, когда у нас есть заголовки политики безопасности контента и хеши целостности подресурсов (SRI).
Сергей Пономарев
4

Из спецификации OAuth :

4.2. Неявный Грант

Тип неявного предоставления используется для получения маркеров доступа (он не поддерживает выдачу маркеров обновления) и оптимизирован для общедоступных клиентов, для которых известно, что они работают с определенным URI перенаправления. Эти клиенты обычно реализуются в браузере с использованием языка сценариев, такого как JavaScript.

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

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

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

Итак, что мы можем рассмотреть:

  1. Это для публичного OAuth, т.е. когда клиент не нуждается в регистрации и не имеет своих собственных клиентских секретов. Но какой сервер аутентификации проверяет URL перенаправления, и этого на самом деле достаточно для безопасности.

  2. Токен доступа появляется в адресной строке браузера, поэтому пользователь может скопировать URL-адрес и отправить его кому-то еще, и он также регистрируется как пользователь, т.е. это что-то вроде фиксации сеанса. Но браузер делает дополнительный редирект с заменой истории, чтобы удалить хеш-фрагмент из URL. Хакер также может украсть токен доступа, прослушивая HTTP-трафик, но это легко защитить с помощью HTTPS. Некоторые вредоносные браузерные расширения могут иметь доступ к URL-адресам из адресной строки, но в конечном итоге это плохая ситуация, как, например, неработающий сертификат HTTPS. И даже поток кода Auth не может помочь здесь, эфир. Итак, я вижу, что передача токена доступа через хеш-фрагмент URL-адреса абсолютно безопасна.

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

Таким образом, я думаю, что мы должны ввести новый поток грантов «безопасный неявный», который работает строго по https, позволяет обновлять токен (или мы должны вообще избавиться от них) и предпочтительнее, чем поток грантов Auth Cose

стокито
источник
3

Для нас наши клиенты хотели иметь возможность проходить аутентификацию с нашим приложением на своих телефонах один раз, и им не нужно было снова входить в систему неделями. С потоком кода вы получаете токен обновления вместе с токеном доступа. Неявный поток не дает вам токен обновления. Токен доступа имеет относительно короткий срок действия, но токены обновления могут иметь срок действия до 90 дней. Всякий раз, когда срок действия маркера доступа истекает, код клиента и сервера может использовать этот токен обновления для получения нового токена доступа и токена обновления, все за кулисами, без какого-либо вмешательства пользователя. Токен обновления можно использовать только один раз. Вы не можете сделать это с неявным потоком. Если вы используете Implicit Flow, и ваш пользователь не взаимодействует с вашим приложением более часа, ему придется снова войти в систему, когда они вернутся. Это не было приемлемо в нашем случае использования,

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

Поток кода потрясающий, но он требует больше работы. В настоящее время у MS нет библиотеки Angular для ее обработки, поэтому мне пришлось написать ее. Если вам интересно, я могу помочь вам с этим.

Тим Харди
источник
2

Мой ответ: вы не можете безопасно и просто внедрить неявный поток с сервером веб-приложений.

Процесс авторизации веб-приложения включает взаимодействие с пользователем, поэтому сервер аутентификации должен перенаправить браузер пользователя обратно на целевую страницу веб-приложения после аутентификации и согласия пользователя (я не вижу другого способа вернуть пользователя в веб-приложение после некоторого взаимодействия с Сервер аутентификации).

То есть токен должен быть передан в веб-приложение с помощью URL перенаправления, верно?

Как объяснил @NicolasGarnier в своем ответе и комментариях, нет способа передать токен как фрагмент URL - он не достигнет сервера веб-приложений.

И передача токена в качестве параметра URL-адреса URL-адреса перенаправления была бы небезопасной даже при HTTPS: если целевая страница (пусть это будет «приветственная страница») содержит ресурсы (изображения, сценарии и т. Д.), Эти ресурсы будут получены браузером через серию запросов HTTP (S) (каждый из которых имеет Refererзаголовок HTTP, содержащий точный URL «страницы приветствия», включая параметры URL). Так токен может просочиться.

Таким образом, кажется, нет способа передать токен в URL перенаправления. Вот почему вам нужен второй вызов (либо с сервера аутентификации на клиент (но по какому URL?), Либо с клиента на сервер аутентификации (второй вызов в потоке кода авторизации))

Lu55
источник