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

обзор

Я ищу, чтобы создать (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)?

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

5 ответов

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

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

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

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

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

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

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

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

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

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

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

Если предположить, что это так, то я подхожу к этому следующим образом (но только потому, что я разработчик 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 и тому подобного.

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

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

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам