OAuth 2 для собственного приложения - в чем разница между общедоступными и конфиденциальными типами клиентов?

Я пытался реализовать OAuth 2-провайдер для веб-сервиса, а затем создал собственное приложение поверх него. Также я хочу предоставить доступ к API сторонним разработчикам.

Я уже прочитал спецификацию OAuth 2 и не могу выбрать правильный поток. Я хочу также аутентифицировать приложения CLI и GUI.

Прежде всего, у нас есть два типа клиентов - публичный и конфиденциальный. Конечно, приложения с графическим интерфейсом и CLI будут общедоступными. Но в чем разница между этими двумя типами? В таком случае для чего мне нужно client_secret, если я могу получить токен доступа без него, просто изменив тип клиента?

Я попытался взглянуть на некоторые реализации API популярных сервисов, таких как GitHub. Но они используют HTTP Basic Auth. Не уверен, что это хорошая идея.

Есть ли какая-то особая разница? Повышает ли один уровень безопасности над другим?

Ответ 1

Что касается разницы между публичными и конфиденциальными клиентами, см. http://tutorials.jenkov.com/oauth2/client-types.html, в котором говорится:

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

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

Конфиденциальные клиенты более безопасны, чем обычные клиенты, но вы не всегда сможете использовать конфиденциальных клиентов из-за ограничений среды, в которой они работают (родные приложения c.q., клиенты в браузере).

Ответ 2

Ответ @HansZ является хорошей отправной точкой, поскольку он проясняет разницу между общедоступным и частным клиентским приложением: способность хранить секрет клиента в секрете.

Но это не отвечает на вопрос: какой профиль OAuth2 я должен использовать для каких вариантов использования? Чтобы ответить на этот критический вопрос, нам нужно глубже вникнуть в проблему.

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

So far, so good. But я disagree that this makes such apps unable accept or store refresh tokens. In fact, the redirect URI used by SPAs и mobile apps is typically localhost and, thus, 100% equivalent to receiving the tokens directly from the token server in response to a Resource Owner Password Credentials Grant (ROPC).

Все идет нормально. Но я не согласен с тем, что такие приложения не могут принимать или сохранять токены обновления. Фактически, URI перенаправления, используемый SPA и мобильными приложениями, обычно localhost и, таким образом, на 100% эквивалентен получению токенов непосредственно от сервера токенов в ответ на RODC (ROPC). Многие авторы указывают, иногда правильно, что OAuth2 на самом деле не выполняет аутентификацию. Фактически, как указано в OAuth2 RFC 6749, для выполнения аутентификации требуются как ROPC, так и клиентские полномочия (CC). См. Раздел 4.3 и Раздел 4.4.

Однако это утверждение верно для грантов Authorization Code и Implicit. Но как на самом деле работает аутентификация для этих доменов?

Обычно пользователь вводит свое имя пользователя и пароль в форму браузера, которая публикуется на сервере аутентификации, который устанавливает cookie для своего домена. Извините, но даже в 2019 году куки - это состояние искусства аутентификации. Почему? Потому что куки - это то, как браузерные приложения поддерживают состояние. В них нет ничего плохого, и cookie файлы браузера достаточно безопасны (домен защищен, приложения JS не могут получить файлы cookie "только http", для безопасности требуется TLS/SSL). Файлы cookie позволяют отображать формы входа только по первому запросу авторизации. После этого текущий идентификатор используется повторно (до истечения сеанса).

Хорошо, тогда что отличается между вышеупомянутым и ROPC? Немного. Разница в том, откуда взята форма для входа. В SPA приложение известно с сервера, прошедшего проверку подлинности TLS/SSL. Так что это практически идентично тому, как форма визуализируется непосредственно сервером. В любом случае, вы доверяете сайту через TLS/SSL. Для мобильного приложения форма, как известно, получена от разработчика приложения через подпись приложения (подписаны приложения из Google Play, Apple Store и т.д.). Итак, опять же, существует механизм доверия, аналогичный TLS/SSL (не лучше, не хуже, зависит от хранилища, CA, распределений доверенного корня и т.д.).

В обоих сценариях возвращается токен, чтобы предотвратить повторную отправку приложением пароля при каждом запросе (именно поэтому HTTP Basic аутентификация плохая).

В обоих случаях сервер аутентификации ДОЛЖЕН быть защищен от атак, которым подвергается любой сервер входа в Интернет. Серверы авторизации не имеют такой проблемы, потому что они делегируют аутентификацию. Однако профили OAuth2 password и client_credentials де-факто служат серверами аутентификации и, следовательно, действительно должны быть жесткими.

Why would you prefer ROPC over an HTML form? Non-interactive cases, such as a CLI, are a common use case. Most CLIs can be considered confidential and, thus, should have both a client_id и client_secret. Note, if running on a shared OS instance, you should write your CLI to pull the client secret и password from a file or, at least, the standard input to avoid secrets и passwords from showing up in process listings!

Почему вы предпочитаете ROPC над формой HTML? Неинтерактивные случаи, такие как CLI, являются распространенным случаем использования. Большинство CLI могут считаться конфиденциальными и поэтому должны иметь как client_id, так и client_secret. Обратите внимание: если вы работаете на экземпляре совместно используемой ОС, вы должны написать свой CLI, чтобы извлечь секретный ключ и пароль клиента из файла или, по крайней мере, стандартный ввод, чтобы избежать появления секретов и паролей в списках процессов! Нативные приложения и SPA - еще одно хорошее применение, imo, потому что эти приложения требуют токены для передачи в службы REST. Однако если для этих приложений также требуются файлы cookie для проверки подлинности, вы, вероятно, захотите использовать код авторизации или неявные потоки и делегировать проверку подлинности обычному серверу веб-входа.

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

Если используется двухфакторная аутентификация, все становится сложнее. Я еще не перешел этот конкретный мост. Но я видел случаи, например, Attlassian, в которых можно использовать ключ API, чтобы разрешить доступ к учетным записям, для которых обычно требуется второй фактор помимо пароля.

Обратите внимание, что даже когда вы размещаете страницу входа в HTML на сервере, вы должны позаботиться о том, чтобы она не была обернута ни IFRAME в браузере, ни каким-либо компонентом Webview в собственном приложении (которое может устанавливать перехватчики для просмотра имя пользователя и пароль, который вы вводите, как работают менеджеры паролей, кстати). Но это еще одна тема, относящаяся к "усилению безопасности сервера входа", но ответы на все вопросы касаются клиентов, соблюдающих соглашения о веб-безопасности и, таким образом, определенный уровень доверия к приложениям.

Несколько заключительных мыслей:

  1. Если токен обновления безопасно доставлен в приложение через любой тип потока, он может быть безопасно сохранен в браузере/собственном локальном хранилище. Браузеры и мобильные устройства достаточно хорошо защищают это хранилище. Это, конечно, менее безопасно, чем хранить токены обновления только в памяти. Так что, может быть, не для банковских приложений... Но у многих приложений очень продолжительные сессии (недели), и вот как это делается.

  2. Не используйте клиентские секреты для публичных приложений. Это только даст вам ложное чувство безопасности. Клиентские секреты подходят только тогда, когда существует защищенный механизм OOB для доставки секрета, и он надежно хранится (например, заблокированы разрешения ОС).