Как создать аутентификацию пользователя из клиентских приложений?

14

Я разрабатывал приложение, которое будет поддерживать многих пользователей. Дело в том, что я не могу понять, как аутентифицировать клиента / пользователя.

Я создаю приложение, такое как http://quickblox.com/, где я предоставляю учетные данные своим пользователям, и они будут использовать их для создания N приложений, в которых они не смогут ввести свое имя пользователя и пароль для аутентификации.

Давайте предположим, что это идет следующим образом. (Так же, как QuickBlox)

1. Пользователь создает учетную запись на моем сайте.
2. Пользователь может создавать N API ключей и секретных учетных данных. (Для нескольких приложений)
3. Пользователь будет использовать эти учетные данные в своих приложениях (Android, iOS, Javascript и т. Д.), Чтобы общаться с моими REST API.
(API REST имеют доступ для чтения и записи.)

Моя забота?

Пользователи будут помещать свои учетные данные (ключ API и секретный ключ) в создаваемые ими приложения. Что если кто-то получит эти ключи и попытается имитировать пользователя? (Декомпилируя APK или напрямую просматривая код JavaScript.

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

Алок Патель
источник
То, что вы пытаетесь сделать, невозможно.
user253751
Есть много приложений, которые делают то же самое. Я не уверен, как они аутентифицируют пользователей.
Алок Патель
Вы пытаетесь аутентифицировать клиентское приложение или пользователя ? Многие приложения аутентифицируют пользователей. Ни один из них не аутентифицирует клиентские приложения в доступном виде.
user253751
Да, под клиентом я имею в виду, я хочу только аутентифицировать пользователя.
Алок Патель
4
О, хорошо, тогда в самой обычной системе аутентификации вы просто заставляете пользователя вводить его имя пользователя и пароль, и отправляете их надежно на сервер, который проверяет их и (надежно) возвращает токен сеанса, а затем вы отправляете токен сеанса в каждый будущий запрос.
user253751

Ответы:

7

Последние несколько лет я разрабатывал REST API. Вы слишком беспокоитесь. Недавно другой пользователь на этом форуме задал вопрос, где он беспокоился о сохранении конечных точек URI в своем клиентском коде JavaScript .

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

Цитата из оригинального ответа:

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

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

Вы должны спроектировать токены доступа вашего приложения, чтобы разрешить только те операции, которые вы хотите разрешить. У вас может быть два типа токенов доступа:

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

Но что кто-то деконструирует исходный код, извлекает токены из приложения, узнает, что такое публичные конечные точки, и использует ваш веб-сервис?

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

Энди
источник
Пока хорошее объяснение, у меня есть вопрос. Допустим, один из моих API - это сборка для извлечения всех связанных данных (A + B) моего пользователя . Мой пользователь использует этот API в своем приложении, чтобы получить filtered data(B) только своего пользователя . Теперь это возможно, или есть ли обходной путь, чтобы третий пользователь не мог украсть все данные (A + B) моего пользователя . Имеет ли это смысл?
Алок Патель
@AlokPatel Нет другого обходного пути, чтобы просто не реализовывать функциональность. Когда вы делаете это, всегда существует риск того, что кто-то подделает свой хеш-идентификатор, чтобы выглядеть как кто-то другой. Программно ваша проблема не может быть решена. Как я уже сказал, если вы не хотите предлагать какую-то функциональность, не реализуйте ее. Поскольку приложения, скорее всего, будут хранить хэш входа в себя, после развертывания приложения ваш ключ API также будет недоступен для общего доступа.
Энди
Спасибо за объяснение. Итак, что я получил, так это то, что API-интерфейсы REST такие же, как и любой веб-сайт, который мы развертываем, они открыты как веб-сайт. Если я не хочу, чтобы пользователь что-то делал, я просто не реализую это в моих REST API. Поэтому я могу иметь отдельные ключи для клиентских библиотек (Android, iOS, JS), которые могут быть скомпрометированы с меньшей функциональностью и разными ключами, которые будут использоваться на стороне сервера (PHP, Java, node.js) с расширенной функциональностью. Надеюсь, это сработает!
Алок Патель
Можете ли вы объяснить мне это? Если вы непосредственно не управляете разработкой приложений, использующих ваш API
Alok Patel
@AlokPatel Я имел в виду, что сейчас вы беспокоитесь о том, что вы даете кому-то доступ к API, они могут распределить доступ и начать злоупотреблять API. Если вы не можете контролировать разработку приложений, использующих ваш API, они могут сделать то же самое даже сами по себе.
Энди
5

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

Допустим, у вас есть API, который вы продаете своим клиентам (разработчикам приложений) по фиксированной ставке 100 фунтов стерлингов в год, неограниченный доступ.

Ну тогда, очевидно, я могу купить вашу услугу за 100 фунтов и продать ее 10 людям по 50 долларов каждая. Вы этого не хотите! поэтому вы пытаетесь придумать ограничение, которое позволит вам продавать свой API без возможности его арбитража.

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

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

Что вам нужно сделать, это передать стоимость каждого вызова API для вашего клиента. т.е. плата за вызов API или установить квоту вызовов в год.

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

Ewan
источник
Я уже планировал ограничить использование моего API в зависимости от количества вызовов API, поэтому проблема, связанная с бизнесом, на данный момент не является моей заботой, меня интересует только кража ключей.
Алок Патель
С деловой точки зрения проблема нерешаема. К сожалению, вы не можете решить это и программно.
Энди
1
Бизнес-проблема. Решается путем взимания платы за звонок. Если ключ украден, ваш клиент проиграет. Не вы. Просто дайте вашему клиенту возможность отменить украденные ключи и скажите им, что у них есть промежуточный API для предотвращения злоупотреблений
Ewan
2

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

Конечно да.

Два принципа (подробности реализации будут следовать):

  1. Фактические конечные точки аутентификации должны быть анонимно открыты для публики.
  2. Сервер должен каким-то образом участвовать в аутентификации клиента и предоставлении ключа API.

Учитывая, что, если клиент делает запрос к конечной точке аутентификации с учетными данными, а сервер аутентифицирует его, сервер может сгенерировать динамический временный токен (временное значение на основе времени). Этот токен должен быть запомнен в клиенте и отправлен с последующими запросами.

Вам понадобится механизм, чтобы периодически «обновлять» токен, то есть получать новый. Просто создайте конечную точку REST, которая позволяет генерировать новый токен из существующего, чтобы избежать необходимости повторной аутентификации из учетных данных.

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

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

Brandon
источник
Интересное решение, хотя оно в основном зависит от того, как клиенты OP будут кодировать свое приложение. Тем не менее, предлагаемый подход может позволить затем сохранить серверную часть ключа API, а после успешной аутентификации их собственных пользователей может переслать временный ключ для фактического использования приложения. таким образом, ничего не сохраняется в самом приложении.
Newtopian
Это верно для всех API. Если потребитель API не использует его должным образом, вещи могут не работать. Это должно быть документированной частью API.
Брэндон
Кстати, есть стандарты, которые помогут сделать это проще, например, OAuth.
Брэндон
0

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

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

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

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

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

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

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

Дэн Корнилеску
источник
0

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

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

Arun
источник
Как обходится JavaScript? Как архитектор для этого?
Алок Патель
Я предполагаю, что вы говорите о создании гибридного приложения. Если это так, то, безусловно, вы сможете создать плагин для хранения ключей. Если вы собираетесь разместить приложение и говорить о мобильном веб-решении, подумайте о рендеринге страницы с использованием контейнера, и вы можете положиться на маркер сеанса, предложенный ранее
Арун
Нет, это не тот случай. Я был бы третьим по величине поставщиком API, мои пользователи будут использовать мой сервис API в своих приложениях. Это может быть Android, iOS, JavaScript и т. Д.
Alok Patel
0

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

У вас возникли проблемы после выдачи учетных данных, вы не можете контролировать, насколько надежно они хранятся. Кроме того, если вам требуется, чтобы пользователь отправил вам учетные данные, тогда кто-то может MITM-соединение и напрямую украсть токены, не беспокоясь об обратном проектировании приложения.

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

Это может немного отклоняться от объема вашего вопроса, но это связано с безопасностью вашего токена, поэтому я упомяну об этом. Чтобы предотвратить тривиальную кражу токена по сети, вы, вероятно, не хотите отправлять токен напрямую, вместо этого вы можете подписать трафик, используя функцию HMAC. Вы можете проверить достоверность сообщения, рассчитав HMAC сообщения на сервере и сравнив его с HMAC, отправленным клиентом. Вы можете использовать токен в качестве ключа для функции HMAC, чтобы только тот, кто знает токен, мог подписывать трафик. Это лучше для безопасности вашего токена, потому что вы никогда не отправляете его напрямую на сервер, поэтому его нельзя перехватить и украсть напрямую. Для получения дополнительной информации о HMACS см. Этот вопрос: /security/20129/how-and-when-do-i-use-hmac/20301

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

ThePragmatist
источник
Я не могу создать библиотеку и поместить в нее секреты, они будут разными для каждого моего пользователя.
Алок Патель
Чтобы уточнить, я предлагал вам создать собственную библиотеку для каждого из ваших пользователей и скрыть их индивидуальные секреты внутри библиотеки. Вам потребуется написать систему для автоматического создания библиотек по требованию для каждого нового пользователя, что может потребовать больше усилий, чем вы хотите.
ThePragmatist
0

Цитирую себя:

Я не могу понять, как аутентифицировать клиента / пользователя ... в котором они не могут ввести свое имя пользователя и пароль для аутентификации.

Это немного противоречит, не так ли? ;)

Как говорили другие, вы не можете. Если приложение использует ключ API, его можно декомпилировать, как вы говорите, чтобы получить ключ (ы) и использовать его тоже.

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

  • белый / черный список IP-адресов
  • дросселирование
  • обнаружение "необычной активности" и ее источник
  • простое обновление ключа
dagnelies
источник