Вопрос

Я пытаюсь разобраться в спецификации OAuth, ее требованиях и любых реализациях, которые я могу найти, и пока это действительно кажется больше проблем, чем того стоит, потому что у меня возникают проблемы с поиском единого ресурса, который объединяет все это воедино.Или, может быть, это просто потому, что я ищу что-то более специализированное, чем большинство учебных пособий.

У меня есть набор существующих API-интерфейсов - некоторые на Java, некоторые на PHP, - которые мне теперь нужно обезопасить, и по ряду причин OAuth кажется правильным решением.К сожалению, моя неспособность отследить нужные ресурсы, которые помогли бы мне наладить работу провайдера, ставит под сомнение эту теорию.Поскольку большая часть этого будет связана с использованием межсистемного API, мне нужно будет внедрить двухуровневого провайдера.Имея это в виду...

  1. Кто-нибудь знает какие-нибудь хорошие руководства по внедрению двуногого поставщика OAuth с PHP?
  2. Учитывая, что у меня есть защищенные API на 2 языках, нужно ли мне внедрять провайдера на обоих или есть способ создать провайдера в качестве "фронт-контроллера", через который я могу перенаправлять все запросы?
  3. Например, при защите служб PHP должен ли я защищать каждый API по отдельности, включая необходимые ресурсы поставщика для каждого?

Спасибо за вашу помощь.

Это было полезно?

Решение

Я бы сделал шаг назад и подумал о том, что вам отправит должным образом аутентифицированный клиент.

Можете ли вы сохранить ключи и учетные данные в общей базе данных, доступной из обоих наборов сервисов, и просто реализовать поставщика OAuth на одном языке?Когда пользователь отправляет запрос в службу (PHP или Java), вы затем сверяетесь с общим хранилищем.Когда пользователь настраивает клиент OAuth, вы делаете все это либо через PHP, либо через Java-приложение (по вашему усмотрению) и сохраняете учетные данные в общей базе данных.

Есть некоторые поставщики Oauth, написанные на других языках, на которые вы, возможно, захотите взглянуть:

Другие советы

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

У меня более или менее был такой же вопрос несколько месяцев назад, и я слышал об "OAuth" большую часть года.Я разрабатывал REST API, который мне нужно было обезопасить, поэтому я начал читать об OAuth...а потом мои глаза начали закатываться назад в моей голове.

Я, вероятно, потратил на это хороший день или два, просматривая и читая, пока не решил, как и вы, что OAuth - это сбивающий с толку мусор, и просто отказался от этого.

Итак, затем я начал изучать способы защиты API в целом и начал лучше понимать, как это сделать.Самым популярным способом, по-видимому, была отправка запросов в API вместе с контрольной суммой из все сообщение (закодированное с секретом, который знаете только вы и сервер), которое сервер может использовать, чтобы решить, было ли сообщение подделано при отправке от клиента, вот так:

  1. Клиент отправляет /user.json/123?showFriends=true&showStats= true&контрольная сумма =kjDSiuas98SD987ad
  2. Сервер получает все это, ищет пользователя "123" в базе данных, загружает его секретный ключ, а затем (используя тот же метод, что и клиент) пересчитывает свою СОБСТВЕННУЮ контрольную сумму с учетом аргументов запроса.
  3. Если сгенерированная сервером контрольная сумма и отправленная клиентом контрольная сумма совпадают, запрос в порядке и выполняется, если нет, он считается подделанным и отклоняется.

Контрольная сумма называется HMAC, и если вам нужен хороший пример этого, это то, что использует Amazon Web Services (хотя они называют аргумент 'signature', а не 'checksum').

Итак, учитывая, что одним из ключевых компонентов этой работы является то, что клиент и сервер должны генерировать HMAC одинаковым образом (иначе они не будут совпадать), должны существовать правила о ТОМ, КАК объединить все аргументы...затем я внезапно понял всю эту чушь с "естественным порядком байтов параметров" из OAuth...это было просто определение правил генерации подписи, потому что это было необходимо.

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

Так что, если вы просто закодируете URI stem в качестве подписи, например:

  • /пользователь.json == askJdla9/kjdas+Askj2l8add

тогда единственное, что в вашем сообщении не может быть изменено, - это URI, все аргументы могут быть изменены, потому что они не являются частью значения "контрольной суммы", которое сервер пересчитает.

В качестве альтернативы, даже если вы включаете КАЖДЫЙ параметр в вычисление, вы все равно подвергаетесь риску "повторных атак", когда злоумышленник-посредник или evesdropped может перехватить вызов API и просто продолжать повторно отправлять его на сервер снова и снова.

Вы можете исправить это, добавив временную метку (всегда используйте UTC) также в вычисление HMAC.

НАПОМИНАНИЕ:Поскольку серверу необходимо вычислить тот же HMAC, вы должны отправить любое значение, которое вы используете в вычислении, КРОМЕ ВАШЕГО СЕКРЕТНОГО КЛЮЧА (по-моему, OAuth называет его consumer_secret).Поэтому, если вы добавляете временную метку, убедитесь, что вы отправляете параметр timestamp вместе с вашим запросом.

Если вы хотите обезопасить API от повторных атак, вы можете использовать одноразовое значение (это одноразовое значение, которое сервер генерирует, передает клиенту, клиент использует его в HMAC, отправляет обратно запрос, сервер подтверждает, а затем помечает это одноразовое значение как "используемое" в базе данных и никогда не разрешает другому запросу использовать его снова).

ПРИМЕЧАНИЕ:одноразовый номер - это действительно точный способ решить проблему "повторной атаки" - временные метки - это здорово, но поскольку компьютеры не всегда имеют синхронизированные значения временных меток, вы должны разрешить приемлемое окно на стороне сервера о том, насколько "старым" может быть запрос (скажем, 10 минут, 30 минут, 1 час....Amazon использует 15 минут), прежде чем мы примем или отклоним его.В этом сценарии ваш API технически уязвим в течение всего периода времени.

Я думаю, что значения одноразового использования - это здорово, но их следует использовать только в тех API, которые критически важны для сохранения их целостности.В моем API мне это не было нужно, но было бы тривиально добавить позже, если бы пользователи этого потребовали...Мне буквально просто нужно было бы добавить таблицу "одноразового использования" в мою базу данных, предоставить новый API таким клиентам, как:

  • /одноразовый номер.json

и затем, когда они отправят это обратно мне в вычислении HMAC, мне нужно будет проверить базу данных, чтобы убедиться, что оно никогда не использовалось ранее, и после использования пометить его как таковой в базе данных, чтобы, если запрос КОГДА-ЛИБО поступит снова с тем же одноразовым номером, я бы его отклонил.

Краткие сведения

В любом случае, короче говоря, все, что я только что описал, это в основном то, что известно как "двуногий OAuth".Нет такого дополнительного шага перехода к полномочному органу (Twitter, Facebook, Google, что угодно) для авторизации клиента, этот шаг удален, и вместо этого сервер неявно доверяет клиенту, если HMAC, которые они отправляют, совпадают.Это означает, что клиент имеет правильный secret_key и подписывает им свои сообщения, поэтому сервер доверяет ему.

Если вы начнете искать в Интернете, это, по-видимому, предпочтительный метод защиты методов API в настоящее время или что-то в этом роде.Amazon почти точно использует этот метод, за исключением того, что они используют немного другой комбинированный метод для своих параметров, прежде чем подписывать все это для генерации HMAC.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top