Создание API для мобильных приложений - Аутентификация и Авторизация

189

обзор

Я ищу, чтобы создать (REST) ​​API для моего приложения. Первоначальное / основное назначение будет предназначаться для мобильных приложений (iPhone, Android, Symbian и т. Д.). Я изучал различные механизмы аутентификации и авторизации для веб-API (изучая другие реализации). Я обернул голову вокруг большинства фундаментальных понятий, но все еще ищу руководство в нескольких областях. Последнее, что я хочу сделать, - это заново изобрести колесо, но я не нахожу никаких стандартных решений, которые бы соответствовали моим критериям (однако мои критерии могут быть ошибочными, поэтому не стесняйтесь критиковать и это). Кроме того, я хочу, чтобы API был одинаковым для всех платформ / приложений, использующих его.

OAuth

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

Требования

  1. Пользователь вводит имя пользователя / пароль в приложение.
  2. Каждый вызов API определяется вызывающим приложением.
  3. Накладные расходы сведены к минимуму, а аспект авторизации интуитивно понятен для разработчиков.
  4. Механизм безопасен как для конечного пользователя (его учетные данные не раскрываются), так и для разработчика (их учетные данные приложения не предоставляются).
  5. Если возможно, не требуйте https (ни в коем случае не жесткое требование).

Мои текущие мысли о реализации

Внешний разработчик запросит учетную запись API. Они получат apikey и apisecret. Каждый запрос потребует как минимум три параметра.

  • apikey - предоставляется разработчику при регистрации
  • отметка времени - удваивается как уникальный идентификатор для каждого сообщения для данного apikey
  • hash - хэш метки времени + apisecret

Apikey требуется для идентификации приложения, отправляющего запрос. Временная метка действует аналогично oauth_nonce и предотвращает / смягчает атаки воспроизведения. Хеш гарантирует, что запрос был действительно выдан владельцем данного apikey.

Что касается аутентифицированных запросов (выполняемых от имени пользователя), я все еще не определился между переходом с маршрутом access_token или комбинацией имени пользователя и пароля. В любом случае, в какой-то момент потребуется имя пользователя и пароль. Поэтому, когда это произойдет, будет использован хеш из нескольких частей информации (apikey, apisecret, timestamp) + пароль. Я хотел бы услышать отзывы об этом К вашему сведению, они должны были бы сначала хэшировать пароль, так как я не храню пароли в моей системе без хэширования.

Вывод

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

Случайные мысли / Бонусные вопросы

Для API, для которых требуется только apikey как часть запроса, как вы препятствуете тому, чтобы кто-то, кроме владельца apikey, мог видеть apikey (с момента отправки в открытом виде) и делать чрезмерные запросы, чтобы выдвинуть их за пределы использования? Может быть, я просто обдумываю это, но разве не должно быть чего-то, что могло бы подтвердить, что запрос был подтвержден владельцу apikey? В моем случае, это было целью apisecret, это никогда не показывается / передается без хеширования.

Говоря о хешах, как насчет md5 против hmac-sha1? Действительно ли имеет значение, когда все значения хэшируются с достаточно длинными данными (например, apisecret)?

Ранее я думал о добавлении соли для каждого пользователя / строки в мой хэш пароля пользователя. Если бы я должен был это сделать, как приложение могло бы создать соответствующий хеш, не зная, какая соль используется?

jsuggs
источник
1
Хотел получить еще несколько комментариев / предложений. Вопрос слишком расплывчатый / двусмысленный?
jsuggs
6
вопрос идеален, но даже спустя почти 2 года реализации oauth кажутся загадочными ... мне труднее всего добиться именно того, что вы обсуждали выше. у меня есть дополнительное измерение: я не хочу использовать пару loginName / password - я хочу использовать проверку личности Google на android / ios (symbian был объявлен WWF "почти вымершим видом"), и я отказываюсь разрабатывать для Windows Mobile (как они называют это в наши дни).
Тони Гил
8
Смешно, что, как все предлагают oauth 2.0, мне еще предстоит найти ясный, простой учебник или пример, в котором используется общий английский для объяснения шагов, требований, действий и того, что нужно сделать…
ChuckKelly
2
Прочитайте этот конкретный поток OAuth2.0 (поток паролей владельца ресурса). Нет перенаправления на сайт. techblog.hybris.com/2012/06/11/…
Франклин
1
Я также ищу тот же ответ. Я нашел хорошую статью, которая была написана недавно. Надеюсь, это поможет. stormpath.com/blog/the-ultimate-guide-to-mobile-api-security
для Rails

Ответы:

44

То, как я думаю о том, чтобы выполнить часть входа в систему в моих проектах:

  1. перед входом пользователь запрашивает login_tokenс сервера. Они создаются и хранятся на сервере по запросу и, вероятно, имеют ограниченный срок службы.

  2. Чтобы войти в систему, приложение вычисляет хэш пароля пользователя, затем хэширует пароль, login_tokenчтобы получить значение, затем они возвращают как login_tokenхеш, так и комбинированный хеш.

  3. Сервер проверяет login_tokenтот, который он сгенерировал, удаляя его из списка допустимых login_tokens. Затем сервер объединяет свой сохраненный хэш пароля пользователя с login_tokenи гарантирует, что он соответствует представленному комбинированному токену. Если это соответствует, вы аутентифицировали своего пользователя.

Преимущества этого состоят в том, что вы никогда не сохраняете пароль пользователя на сервере, пароль никогда не передается в открытом виде, хеш пароля передается только в открытом виде при создании учетной записи (хотя могут быть способы обойти это), и это должно быть защищен от повторных атак, поскольку login_tokenудаляется из БД при использовании.

Майкл Андерсон
источник
Спасибо, я забыл добавить часть о хешировании пароля на стороне приложения. Я не храню пароли своих пользователей в открытом виде (хеширую перед сохранением).
jsuggs
2
Я вижу обратную сторону этого метода: вы не можете хранить соленые пароли в БД. Если злоумышленники возложат руки на вашу БД, им не нужно будет ничего расшифровывать. Поскольку хэш пароля является реальным паролем в этой схеме.
Sigod
2
@sigod Вы правы. Хотя я думаю, что здесь есть фундаментальная дихотомия - вам нужно либо доверять своему транспорту, либо доверять своему хранилищу. Системы входа в систему, которые используют соленые пароли, доверяют транспортному уровню и, таким образом, передают пароль от пользователя системе аутентификации в открытом виде. Этот случай не доверяет транспортному уровню (я думаю, это потому, что на платформе, на которую я нацелился, была плохая поддержка SHTTP). Если вы доверяете транспортному уровню, вы можете сделать другие компромиссы.
Майкл Андерсон
У меня 3 проблемы: 1) как пароль пользователя никогда не сохраняется на сервере? на шаге 2 вы упомянули, что он хранит хешированный пароль пользователя. 2) Пароль пользователя никогда не передается в открытом виде. Но на самом деле он хешируется на клиенте, а затем сравнивается с хешированным паролем на сервере, что почти равнозначно передаче и хранению в открытом виде, какой смысл это делать? 3) Этот метод предполагает, что злоумышленник не знает, как хэшируются login_token + пароль, что нарушает принцип Kerckhoffs и делает его действительно небезопасным.
Тамер Шлаш
14

Это много вопросов в одном, я думаю, что многим людям не удалось прочесть весь путь до конца :)

Мой опыт проверки подлинности веб-службы заключается в том, что люди обычно переоценивают ее, и проблемы такие же, как и на веб-странице. Возможные очень простые опции будут включать https для шага входа в систему, возвращать токен, требовать его включения в будущие запросы. Вы также можете использовать http обычную аутентификацию и просто передавать вещи в заголовок. Для дополнительной безопасности часто поворачивайте / истекайте токены, проверяйте, что запросы поступают от одного и того же IP-блока (хотя это может привести к путанице, когда мобильные пользователи перемещаются между ячейками), в сочетании с ключом API или подобным. В качестве альтернативы, сделайте шаг oauth «ключ запроса» (кто-то предложил это уже в предыдущем ответе, и это хорошая идея) перед аутентификацией пользователя и используйте его в качестве необходимого ключа для генерации токена доступа.

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

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

Надеюсь, что это помогает, удачи :)

Лорна Митчелл
источник
Спасибо за ответ. Я искал xAuth, и это может быть путь, по которому я могу пойти, чтобы я мог в итоге установить oAuth, что делает более стандартизированный процесс взаимодействия с API.
jsuggs
9

Итак, что вам нужно, это какой-то механизм аутентификации на стороне сервера, который будет обрабатывать аспекты аутентификации и авторизации мобильного приложения?

Если предположить, что это так, то я бы подошел к этому следующим образом (но только потому, что я Java-разработчик, поэтому парень на C # сделал бы это по-другому):

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

  1. Это будет работать только через HTTPS, чтобы предотвратить подслушивание.
  2. Он будет основан на комбинации RESTEasy , Spring Security и CAS (для единого входа в несколько приложений).
  3. Он будет работать как с браузерами, так и с веб-клиентскими приложениями.
  4. Будет веб-интерфейс управления учетными записями, позволяющий пользователям редактировать свои данные, а администраторам (для определенных приложений) изменять уровни авторизации.

Клиентская библиотека безопасности / приложение

  1. Для каждой поддерживаемой платформы (например, Symbian, Android, iOS и т. Д.) Создайте подходящую реализацию библиотеки безопасности на родном языке платформы (например, Java, ObjectiveC, C и т. Д.)
  2. Библиотека должна управлять формированием запроса HTTPS с использованием доступных API для данной платформы (например, Java использует URLConnection и т. Д.)
  3. Потребители общей библиотеки аутентификации и авторизации (потому что это все, что есть) будут кодировать определенный интерфейс и не будут рады, если он когда-либо изменится, поэтому убедитесь, что он очень гибкий. Следуйте существующим проектным решениям, таким как Spring Security.

Итак, теперь, когда вид с высоты 30 000 футов завершен, как вы это делаете? Что ж, не так сложно создать систему аутентификации и авторизации на основе перечисленных технологий на стороне сервера с клиентом браузера. В сочетании с HTTPS платформы будут обеспечивать безопасный процесс на основе общего токена (обычно представляемого в виде cookie), сгенерированного процессом аутентификации и используемого всякий раз, когда пользователь хочет что-то сделать. Этот токен предоставляется клиентом серверу при каждом запросе.

В случае локального мобильного приложения кажется, что вы ищете решение, которое выполняет следующие действия:

  1. Клиентское приложение имеет определенный список контроля доступа (ACL), контролирующий доступ во время выполнения к вызовам методов. Например, данный пользователь может читать коллекцию из метода, но его ACL-список разрешает доступ только к объектам, у которых в имени есть символ Q, поэтому некоторые данные в коллекции спокойно обрабатываются перехватчиком безопасности. В Java это просто, вы просто используете аннотации Spring Security в вызывающем коде и реализуете подходящий процесс ответа ACL. На других языках вы сами по себе и, вероятно, должны будете предоставить стандартный код безопасности, который будет вызывать вашу библиотеку безопасности. Если язык поддерживает AOP (Аспектно-ориентированное программирование), используйте его в полной мере для этой ситуации.
  2. Библиотека безопасности кэширует полный список авторизаций в свою личную память для текущего приложения, так что ей не нужно оставаться подключенным. В зависимости от продолжительности сеанса входа в систему это может быть разовая операция, которая никогда не повторяется.

Что бы вы ни делали, не пытайтесь изобрести свой собственный протокол безопасности или используйте безопасность из-за неясности. Вы никогда не сможете написать лучший алгоритм для этого, чем те, которые в настоящее время доступны и бесплатны. Также люди доверяют хорошо известным алгоритмам. Поэтому, если вы скажете, что ваша библиотека безопасности обеспечивает авторизацию и аутентификацию для локальных мобильных приложений, использующих комбинацию зашифрованных токенов SSL, HTTPS, SpringSecurity и AES, вы сразу же получите авторитет на рынке.

Надеюсь, что это поможет, и удачи в вашем предприятии. Если вам нужна дополнительная информация, дайте мне знать - я написал немало веб-приложений на основе Spring Security, ACL и тому подобного.

Гэри Роу
источник
Спасибо, хорошая информация. Пара вопросов. Во-первых, если подслушивание приемлемо (не уверен, является ли это / нет, мое приложение не имеет в виду никакой личной / ценной информации, но если бы оно изменило мое обоснование, изменилось бы), тогда действительно ли требуется HTTPS?
jsuggs
Вы можете управлять всей системой за пределами HTTPS, если хотите. HTTPS предназначен только для защиты секретной информации, поэтому я предполагаю, что на этапе аутентификации вы будете делать это через HTTPS, чтобы обеспечить некоторую гарантию того, что ваше имя пользователя / пароль / секрет хранится в секрете. После того, как токен передан в ответе, дальнейшие запросы могут быть сделаны в открытом виде, если информация, содержащаяся в потоке (для которой требовалась аутентификация), не нуждается в защите от перехватчиков.
Гэри Роу
Кроме того, это описание протокола аутентификации CAS может быть полезно: jasig.org/cas/protocol
Гари Роу,
9

Twitter решил проблему с внешним приложением в oAuth, поддержав вариант, который они называют xAuth . К сожалению, уже есть множество других схем с таким названием, поэтому разобраться может быть сложно.

Протокол является OAuth, за исключением того, что пропускает лексемы фазы запроса и просто сразу же выдает маркер доступа пары после получения имени пользователя и пароля. (Начиная с шага E здесь .) Этот первоначальный запрос и ответ должны быть защищены- он отправляет имя пользователя и пароль в виде открытого текста и получает обратно токен доступа и секретный токен. Как только пара токенов доступа настроена, то, был ли начальный обмен токеном с помощью модели oAuth или модели xAuth, не имеет значения для клиента и сервера до конца сеанса. Это дает преимущество в том, что вы можете использовать существующую инфраструктуру oAuth и иметь практически такую ​​же реализацию для мобильных / веб / настольных приложений. Основным недостатком является то, что приложению предоставляется доступ к имени пользователя и паролю клиента, но, похоже, ваши требования требуют такого подхода.

В любом случае, я бы хотел согласиться с вашей интуицией и интуицией нескольких других: здесь не пытайтесь создавать что-то новое с нуля. Протоколы безопасности могут быть легко запущены, но их всегда сложно сделать хорошо, и чем более запутанными они становятся, тем меньше вероятность того, что ваши сторонние разработчики смогут внедрить против них. Ваш гипотетический протокол очень похож на o (x) Auth - api_key / api_secret, nonce, sha1 hash - но вместо возможности использовать одну из множества существующих библиотек, которые ваши разработчики должны будут развернуть самостоятельно.

lantius
источник
2
Я также должен отметить, что похоже, что конечная точка 'skip request token' будет в oAuth 2, она указана в текущем проекте как тип предоставления доступа "пароль". См. Раздел 4.1.2: tools.ietf.org/html/draft-ietf-oauth-v2-10#section-4.1.2
lantius
Как я уже упоминал в Lonra, я больше интересуюсь xAuth и, в частности, по причинам, которые вы упомянули в конце ... разработчики могут «готовить» инструменты / библиотеки oAuth для взаимодействия с моим API, что «хорошо» ,
jsuggs
6

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

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

В предлагаемом решении вы упоминаете, что потребуется минимум три параметра:

  • apikey - предоставляется разработчику при регистрации
  • отметка времени - удваивается как уникальный идентификатор для каждого сообщения для данного apikey
  • hash - хэш метки времени + apisecret

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

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

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

Еще один способ смягчить чрезмерное использование в API , который не требует логина, чтобы душить трафик и потенциально идентифицировать и блокировать подозрительный IP - адрес. Объем усилий, которые вы хотите предпринять, во многом зависит от того, насколько ценны ваши данные.

Кроме того, вы можете легко начать заниматься моей повседневной работой. В любом случае, это еще один аспект защиты API, который я считаю важным и хотел бы отметить.

ThePragmatist
источник