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

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

Вместе с потоком "Код авторизации" клиент (обычно веб-сервер) получает только код авторизации после того, как владелец ресурса (то есть пользователь) предоставил доступ. С помощью этого кода авторизации клиент затем делает другой вызов API, передавая client\_id и client\_secret вместе с кодом авторизации, чтобы получить токен доступа. [Все хорошо описано здесь](https://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified).

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

Вопрос:  **Зачем беспокоиться о потоке "Код авторизации", когда "Неявные" потоки потока будут в порядке? Почему бы не использовать "Неявный" для веб-сервера?**

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

 

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

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

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

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

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

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

* Они не являются частью HTTP-запроса, поэтому они не могут быть прочитаны серверами и поэтому не могут быть перехвачены промежуточными серверами/маршрутизаторами (это важно).

 (function(w, d, n, s, t) {
 w[n] = w[n] || [];
 w[n].push(function() {
 Ya.Context.AdvManager.render({
 blockId: "R-A-248011-3",
 renderTo: "yandex\_rtb\_R-A-248011-3",
 async: true
 });
 });
 t = d.getElementsByTagName("script")[0];
 s = d.createElement("script");
 s.src = "//an.yandex.ru/system/context.js";
 s.async = true;
 t.parentNode.insertBefore(s, t);
 })(this, this.document, "yandexContextAsyncCallbacks");

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

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

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

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

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



**Неявный поток делает весь поток довольно простым, но в то же время менее безопасным**.  

Этот поток следует использовать для приложений, которым требуется временный доступ (несколько часов) к данным пользователей.  

 (function(w, d, n, s, t) {
 w[n] = w[n] || [];
 w[n].push(function() {
 Ya.Context.AdvManager.render({
 blockId: "R-A-248011-4",
 renderTo: "yandex\_rtb\_R-A-248011-4",
 async: true
 });
 });
 t = d.getElementsByTagName("script")[0];
 s = d.createElement("script");
 s.src = "//an.yandex.ru/system/context.js";
 s.async = true;
 t.parentNode.insertBefore(s, t);
 })(this, this.document, "yandexContextAsyncCallbacks");

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



Из [спецификации OAuth](https://tools.ietf.org/html/rfc6749#section-4.2):

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

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

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

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



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

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

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

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

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

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