REST API Аутентификация на основе токенов - PullRequest
119 голосов
/ 19 марта 2012

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

Действительно ли это лучше, чем просто требовать от клиентов использовать HTTP Basic Auth при каждом запросе и кэшировать вызовы на стороне сервера службы аутентификации?

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

В настоящее время токены приобретаются следующим образом:

curl -X POST localhost/token --data "api_key=81169d80...
                                     &verifier=2f5ae51a...
                                     &timestamp=1234567
                                     &user=foo
                                     &pass=bar"

api_key, timestamp и verifier требуются для всех запросов.«Верификатор» возвращается:

sha1(timestamp + api_key + shared_secret)

Мое намерение состоит в том, чтобы разрешать вызовы только от известных сторон и дословно предотвратить повторное использование вызовов.

Достаточно ли этого достаточно??Underkill?Overkill?

Имея токен в руках, клиенты могут приобретать ресурсы:

curl localhost/posts?api_key=81169d80...
                    &verifier=81169d80...
                    &token=9fUyas64...
                    &timestamp=1234567

Для простейшего возможного вызова это выглядит ужасно многословно.Учитывая, что shared_secret будет встроен (как минимум) в приложение для iOS, из которого, как я полагаю, его можно извлечь, это вообще что-то, кроме ложного чувства безопасности? *

Ответы [ 3 ]

92 голосов
/ 19 марта 2012

Позвольте мне разделить все и решить подойти к каждой проблеме по отдельности:

Аутентификация

Для аутентификации у baseauth есть преимущество в том, что он является зрелым решением науровень протокола.Это означает, что многие «могут возникнуть позже» проблем уже решены для вас.Например, при использовании BaseAuth пользовательские агенты знают, что пароль является паролем, поэтому они не кэшируют его.

загрузка сервера аутентификации

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

Безопасность передачи

Если вы можете использоватьSSL-соединение, это все, что нужно, соединение безопасное *.Чтобы предотвратить случайное многократное выполнение, вы можете отфильтровать несколько URL-адресов или попросить пользователей включить в URL случайный компонент («nonce»).

url = username:key@myhost.com/api/call/nonce

Если это невозможно, а передаваемая информация не является секретнойЯ рекомендую защитить запрос с помощью хэша, как вы предложили при использовании токена.Поскольку хеш обеспечивает безопасность, вы можете указать своим пользователям предоставить хеш в качестве пароля baseauth.Для повышения надежности я рекомендую использовать случайную строку вместо метки времени в качестве «одноразового номера» для предотвращения атак воспроизведения (в течение одной секунды могут быть сделаны два допустимых запроса).Вместо того, чтобы предоставлять отдельные поля «общий секретный ключ» и «ключ API», вы можете просто использовать ключ API в качестве общего секретного ключа, а затем использовать соль, которая не изменяется, чтобы предотвратить атаки радужных таблиц.Поле имени пользователя кажется хорошим местом для размещения одноразового номера, поскольку оно является частью аутентификации.Так что теперь у вас есть чистый звонок, подобный этому:

nonce = generate_secure_password(length: 16);
one_time_key = nonce + '-' + sha1(nonce+salt+shared_key);
url = username:one_time_key@myhost.com/api/call

Это правда, что это немного трудоемко.Это потому, что вы не используете решение уровня протокола (например, SSL).Поэтому было бы неплохо предоставить пользователям какой-то SDK, чтобы, по крайней мере, им не пришлось проходить через него самостоятельно.Если вам нужно сделать это таким образом, я нахожу уровень безопасности подходящим (just-right-kill).

Безопасное секретное хранилище

Это зависит от того, кто вы пытаетесьпомешатьЕсли вы запрещаете людям, имеющим доступ к телефону пользователя, использовать вашу службу REST от имени пользователя, было бы неплохо найти какой-нибудь API-интерфейс для ключей в целевой ОС и иметь SDK (или разработчик) для храненияключ там.Если это невозможно, вы можете по крайней мере усложнить получение секрета, зашифровав его и сохранив зашифрованные данные и ключ шифрования в отдельных местах.

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

(*) РЕДАКТИРОВАТЬ: SSL-соединений больше не должно бытьсчитается безопасным без дополнительных шагов для проверки их.

16 голосов
/ 02 сентября 2014

Чистый API RESTful должен использовать базовые стандартные функции протокола:

  1. Для HTTP API RESTful должен соответствовать существующим стандартным заголовкам HTTP.Добавление нового заголовка HTTP нарушает принципы REST.Не изобретайте велосипед заново, используйте все стандартные функции стандартов HTTP / 1.1, включая коды ответов о состоянии, заголовки и т. Д.Веб-службы RESTFul должны использовать стандарты HTTP и полагаться на них.

  2. Службы RESTful ДОЛЖНЫ БЕЗУСЛОВНЫМИ.Любые уловки, такие как аутентификация на основе токенов, которая пытается запомнить состояние предыдущих запросов REST на сервере, нарушают принципы REST.Опять же, это ДОЛЖНО;то есть, если ваш веб-сервер сохраняет какую-либо информацию, связанную с контекстом запроса / ответа, на сервере, пытаясь установить какой-либо сеанс на сервере, то ваша веб-служба НЕ имеет состояния без сохранения состояния.И если он НЕ сохраняет состояние, это НЕ RESTFul.

Итог: Для целей аутентификации / авторизации вы должны использовать стандартный заголовок авторизации HTTP.То есть вы должны добавлять заголовок авторизации / аутентификации HTTP в каждом последующем запросе, который необходимо аутентифицировать.API REST должен соответствовать стандартам схемы аутентификации HTTP. Особенности форматирования этого заголовка определены в стандартах RFC 2616 HTTP 1.1 - раздел 14.8 Авторизация RFC 2616 и в аутентификации HTTP RFC 2617: базовая и дайджест-аутентификация доступа.

Я разработал службу RESTful для приложения Cisco Prime Performance Manager.Найдите в Google документ REST API, который я написал для этого приложения, чтобы узнать больше о соответствии API RESTFul здесь .В этой реализации я решил использовать HTTP «базовую» схему авторизации.- проверить версию 1.5 этого документа REST API и выполнить поиск авторизации в документе.

2 голосов
/ 28 ноября 2015

В сети протокол с отслеживанием состояния основан на наличии временного токена, который обменивается между браузером и сервером (через заголовок cookie или перезапись URI) при каждом запросе.Этот токен обычно создается на стороне сервера и представляет собой фрагмент непрозрачных данных с определенным временем жизни, и он имеет единственную цель - идентифицировать определенного агента веб-пользователя.Таким образом, токен является временным и становится СОСТОЯНИЕМ, которое веб-сервер должен поддерживать от имени клиентского пользовательского агента в течение этого разговора.Таким образом, общение с использованием токена таким образом является STATEFUL.И если диалог между клиентом и сервером является STATEFUL, он не является RESTful.

Имя пользователя / пароль (отправленные в заголовке авторизации) обычно сохраняются в базе данных с целью идентификации пользователя.Иногда пользователь может иметь в виду другое приложение;однако имя пользователя / пароль НИКОГДА не предназначены для идентификации конкретного пользовательского агента веб-клиента.Диалог между веб-агентом и сервером, основанный на использовании имени пользователя / пароля в заголовке авторизации (после базовой HTTP-авторизации), является STATELESS, поскольку интерфейс веб-сервера не создает и не поддерживает какую-либо информацию STATE вообще.от имени определенного агента пользователя веб-клиента.И, исходя из моего понимания REST, протокол четко утверждает, что диалог между клиентами и сервером должен быть STATELESS.Поэтому, если мы хотим иметь настоящую службу RESTful, мы должны использовать имя пользователя / пароль (см. RFC, упомянутый в моем предыдущем посте) в заголовке авторизации для каждого отдельного вызова, а НЕ токена типа восприятия (например, токены сеанса, созданные на веб-серверах)., OAuth-токены, созданные на серверах авторизации и т. Д.).

Я понимаю, что несколько вызываемых REST-провайдеров используют токены, такие как OAuth1 или OAuth2 accept-tokens, которые передаются как «Authorization: Bearer» в заголовках HTTP.Однако мне кажется, что использование этих токенов для сервисов RESTful нарушило бы истинное значение STATELESS, которое охватывает REST;потому что эти токены являются временным фрагментом данных, созданным / поддерживаемым на стороне сервера для идентификации конкретного пользовательского агента веб-клиента в течение действительной продолжительности этого разговора веб-клиент / сервер.Поэтому любой сервис, использующий эти токены OAuth1 / 2, не должен называться REST, если мы хотим придерживаться ИСТИННОГО значения протокола STATELESS.

Rubens

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...