REST API авторизация и аутентификация (веб + мобильный)

Я читал об oAuth, API Amazon REST, HTTP Basic/Digest и т. Д., Но не могу объединить все это в "один кусок". Вероятно, это самая близкая ситуация - Создание API для мобильных приложений - Аутентификация и авторизация

Хотелось бы построить API-ориентированный сайт - сервис. Поэтому (в начале) у меня будет API в центре, а веб-сайт (PHP + MySQL) будет подключаться через cURL, Android и iPhone через их сетевые интерфейсы. Итак, 3 основных клиента - 3 ключа API. И любой другой разработчик также может разрабатывать через интерфейс API, и они получат свой собственный ключ API. Действия API будут приниматься / отклоняться в зависимости от статуса userLevel. Если я администратор, я могу что-либо удалять и т. Д., Все остальные могут манипулировать только своими локальными (учетными) данными.

Во-первых, авторизация. Должен ли я использовать oAuth + xAuth или мою реализацию типа "что-то вроде меня" (см. http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/RESTAuthentication.html?r=9197)? Как я понимаю, на сервисе Amazon пользователь == пользователь API (есть ключ API). В моем сервисе мне нужно разделить стандартных пользователей / учетную запись (ту, которая зарегистрирована на сайте) и учетные записи разработчиков (у которых должен быть свой ключ API).

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

Я читал о получении токена через api.example.org/auth после (через HTTPS, HTTP Basic) размещения моего имени пользователя и пароля, а затем пересылать его при каждом следующем запросе. Как управлять токенами, если я вошел в систему одновременно на Android и на сайте? А как насчет атаки "человек посередине", если я использую SSL только при первом запросе (при передаче имени пользователя и пароля) и только HTTP при каждом другом? Разве это не проблема в этом примере Пароль защищает службу REST?

1 ответ

Решение

Как всегда, лучший способ защитить ключ - не передавать его.

Тем не менее, мы обычно используем схему, где каждый "ключ API" состоит из двух частей: несекретного идентификатора (например, 1234) и секретного ключа (например, байта [64]).

  • Если вы выдаете ключ API, сохраните его (соленый и хэшированный) в базе данных вашего сервиса.
  • Если вы выдаете учетные записи пользователей (защищенные паролем), сохраните пароли (соленые и хэшированные) в базе данных вашего сервиса

Теперь, когда потребитель впервые получает доступ к вашему API, подключите его

  • Отправьте параметр "username" ("john.doe" не секретно)
  • Отправьте параметр "APIkeyID" ("1234", не секрет)

и верни его

  • соли из вашей базы данных (в случае, если один из параметров неверен, просто верните несколько повторяемых солей - например, sha1(имя пользователя +"notverysecret").
  • Отметка времени сервера

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

Потребитель теперь должен рассчитать соленые хэши API-ключа и пароля. Таким образом, потребитель получает те же хеши для пароля и ключа API, что и в вашей базе данных, но без каких-либо секретов.

Теперь, когда потребитель впоследствии получает доступ к вашему API, чтобы сделать реальную работу, попросите его

  • Отправьте параметр "username" ("john.doe" не секретно)
  • Отправьте параметр "APIkeyID" ("1234", не секрет)
  • Отправьте параметр "RequestSalt" (байт [64], случайный, не секретный)
  • Отправить параметр "RequestTimestamp" (рассчитывается по времени клиента и известному смещению)
  • Отправьте параметр "RequestToken" (хеш (passwordhash+request_salt+request_timestamp+apikeyhash))

Сервер не должен принимать временные метки больше, чем, скажем, 2 секунды в прошлом, чтобы обезопасить себя от атаки повторного воспроизведения.

Теперь сервер может вычислять тот же хеш (passwordhash + request_salt + request_timestamp + apikeyhash), что и клиент, и быть уверенным, что

  • клиент знает ключ API,
  • клиент знает правильный пароль
Другие вопросы по тегам