Як архітектуру автентифікації користувачів з клієнтських додатків?


14

Я розробляв додаток, який підтримуватиме багатьох користувачів. Справа в тому, що я не в змозі зрозуміти, як автентифікувати клієнта / користувача.

Я будую такий додаток, як http://quickblox.com/, де я дам облікові дані своїм користувачам, і вони використовуватимуть їх для створення N додатків, у яких вони не можуть ввести своє ім’я користувача та пароль для отримання автентичності.

Припустимо, що йде так. (Так само, як QuickBlox)

1. Користувач створює обліковий запис на моєму веб-сайті.
2. Користувач може створювати N ключів API та виділяти облікові дані. (Для декількох додатків)
3. Користувач використовуватиме ці облікові дані у своїх програмах (Android, iOS, Javascript тощо) для розмови з моїми API REST.
(API REST мають доступ для читання та запису.)

Моя стурбованість?

Користувачі будуть розміщувати свої облікові дані (ключ API та виділяти ключ) у створених ними програмах, що робити, якщо хтось отримає ці ключі та спробує імітувати користувача? (Декомпілюючи APK або безпосередньо вивчивши код JavaScript.

Я десь помиляюся?
Я плутати архітектор цього трирівневого механізму користувача.


Те, що вам здається, намагаєтеся зробити, неможливо.
користувач253751

Існує багато додатків, які роблять те саме. Я не впевнений, як вони аутентифікують користувачів.
Алок Патель

Ви намагаєтесь перевірити автентифікацію клієнтської програми чи користувача ? Багато додатків підтверджують автентичність користувачів. Жоден з них не засвідчує автентифікацію клієнтських додатків.
користувач253751

Так, клієнтом, я маю на увазі, що я хочу лише автентифікувати користувача.
Алок Патель

4
О, тоді в найбільш типовій системі аутентифікації ви просто дозволите користувачеві ввести своє ім’я користувача та пароль і надійно надіслати їх серверу, який перевіряє їх і (надійно) поверне маркер сеансу, а потім ви надішлите маркер сеансу в кожен майбутній запит
користувач253751

Відповіді:


7

Я розробляв API REST протягом останніх кількох років. Ви занадто переживаєте. Нещодавно інший користувач на цій дошці задав запитання, де він турбувався про збереження кінцевих точок URI у своєму коді на стороні JavaScript .

До вас діють ті самі правила, що і до розробника JavaScript. Якщо ви дозволяєте людям ззовні інтегрувати ваш API, ваш API має таку саму видимість, як і звичайний веб-сайт, і ви повинні ставитися до нього так само.

Цитата з оригінальної відповіді:

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

Ваш REST API повинен бути надійним, щоб не допускати недійсних операцій, таких як доступ до даних від іншого користувача.

Вам слід розробити маркери доступу до додатків, щоб вони дозволяли лише ті операції, які ви хочете дозволити. Ви можете мати два типи маркерів доступу:

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

Але що хтось деконструює вихідний код, виймає маркери з програми, дізнається, що таке загальнодоступні точки, і зловживає вашою веб-службою?

Якщо ви безпосередньо не керуєте розробкою програм, що споживають ваш API, ніщо насправді не забороняє людям зловживати вашим API таким же чином безпосередньо з програми.


Добре пояснення поки що, у мене все-таки питання. Скажімо, один з моїх API є побудовою для отримання всіх пов'язаних даних (A + B) мого користувача . Мій користувач використовує цей API у своєму додатку, щоб отримати filtered data(B) лише свого користувача . Тепер це можливо, чи є якесь рішення, щоб запобігти третьому користувачеві красти всі дані (A + B) мого користувача . Чи є сенс?
Алок Патель

@AlokPatel Немає іншого вирішення, щоб просто не реалізувати функціонал. Коли ви це робите, завжди існує ризик того, що хтось підробить хеш-код своєї особи, щоб виглядати як хтось інший. Програмно ваша проблема не може бути вирішена. Як я вже говорив, якщо ви не хочете пропонувати якусь функціональність, не виконуйте її. Оскільки додатки, ймовірно, зберігають хеш для входу в них, коли програма буде розгорнута, такий ваш API 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.


Я вже планував обмежити використання мого API на основі кількості викликів API, тому проблема, пов’язана з бізнесом, на даний момент не хвилює мене, мене турбують лише вкрадені ключі.
Алок Патель

З точки зору бізнесу, проблема нерозв'язна. На жаль, ви не можете це вирішити і програмно.
Енді

1
Бізнес-проблеми вирішуються за рахунок оплати за дзвінок. Якщо ключ вкрадений, ваш клієнт втрачає. Не ти. Просто дайте своєму клієнтові скасувати викрадені ключі та скажіть йому, що він має проміжну версію для запобігання зловживань
Ewan

2

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

Звичайно, це так.

Два принципи (слідують деталі впровадження):

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

З огляду на те, що якщо клієнт подає запит на кінцеву точку аутентифікації за допомогою облікових даних, і сервер його автентифікує, сервер може генерувати динамічний тимчасовий маркер (тимчасове значення, що базується на часі). Цей маркер слід пам'ятати клієнту та надсилати з подальшими запитами.

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

Якщо ви намагаєтеся уникати повторної автентифікації кінцевого користувача, то ця автентифікація може бути початковою одноразовою установкою в додатку, коли він буде встановлений.

Це рішення просто дозволяє уникнути необхідності зберігання статичного маркера, вбудованого в бінарний додаток. Маркер генерується на ходу сервером лише у відповідь на успішну аутентифікацію. Щоб шкідливий користувач перевіряв вашу програму та намагався отримати несанкціонований доступ до API, вони все одно повинні мати автентифікацію, як ніхто інший.


Цікаве рішення, хоча воно в основному покладається на те, як клієнти ОП будуть кодувати свою програму. Це говорить про те, що запропонований підхід може потім дозволяти зберігати сторону сервера ключових API і після успішної автентифікації власних користувачів може переслати тимчасовий ключ для фактичного використання додатка. таким чином нічого не зберігається в самому додатку.
Ньютопський

Це справедливо для всіх API. Якщо споживач API не споживає його належним чином, речі можуть не працювати. Це повинно бути документально підтвердженою частиною API.
Брендон

До речі, існують стандарти, які допоможуть зробити це простішим, як OAuth.
Брендон

0

Якщо у вас є унікальні ключі за програмою, ви можете використовувати їх лише під час початкової автентифікації підключення, ініційованої клієнтом, після чого переходите на унікальний маркер автентифікації за програмою.

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

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

Щоразу, коли обмін з клієнтом не синхронізується (деяка помилка протоколу), ваш сервер вимагатиме повторної автентифікації (через відповідь про помилку на наступний запит клієнта або підкріплений під час дійсної відповіді на запит клієнта для приклад).

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

Ще краще було б зберегти маркер на стороні клієнта таким чином, щоб перезапущений клієнт міг продовжуватись з того місця, де його попередник ліворуч - значно звузивши отвір для імітації.

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


0

З того, що я знаю, те, що ви згадали, - єдиний спосіб зробити це. Додаток, що зберігає ключ, безумовно, є ризиком, але існують різні способи його обійти. Ви завжди можете використовувати сховище клавіш для зберігання ключа, ніж жорстке кодування, таким чином, примушуючи одноразовий логін.

Крім того, слід розглянути можливість прив’язки ключа до клієнта, таким чином, якщо хтось імітує, у вас повинен бути рівень безпеки, щоб перевірити клієнта, ключ та агенти користувача, щоб негайно заблокувати запит. Потрібно застосувати для повторної видачі або переконання, що ключі не імітуються.


Що таке робота над JavaScript? Як архітектор для цього?
Алок Патель

Я припускаю, що ви говорите про створення гібридної програми. Якщо це так, то, безумовно, ви повинні мати можливість створити плагін для зберігання ключів. Якщо ви збираєтеся розмістити додаток і говорити про веб-рішення для мобільних пристроїв, тоді подумайте про рендеринг сторінки за допомогою контейнера, і ви можете покластися на маркер сесії, запропонований раніше
Arun

Ні, це не так. Я став би третім провідним постачальником 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

0

Цитуючи себе:

Я не можу зрозуміти, як автентифікувати клієнта / користувача ..., коли вони не можуть ввести своє ім'я користувача та пароль для отримання автентичності.

Тепер це трохи суперечність, чи не так? ;)

Як казали інші, ви не можете. Якщо додаток використовує ключ API, його можна декомпілювати, як ви говорите, щоб отримати ключ (и) та використовувати його також.

Крім необхідності додаткової належної автентифікації користувача, ви можете лише обмежити шкоду:

  • IP-адреси білого списку / чорного списку
  • дроселювання
  • виявлення "незвичної активності" та його джерело
  • просте оновлення ключів
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.