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


189

Огляд

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

oAuth

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

Вимоги

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

Мої поточні думки про реалізацію

Зовнішній розробник запитає акаунт API. Вони отримають апікею та апісекрет. Кожен запит вимагатиме як мінімум трьох параметрів.

  • apikey - надається розробнику при реєстрації
  • мітка часу - являє собою унікальний ідентифікатор для кожного повідомлення для даної apikey
  • хеш - хеш часової позначки + апісекрет

Apikey необхідний для ідентифікації програми, що видає запит. Часова позначка діє аналогічно oauth_nonce і уникає / пом'якшує повторні атаки. Хеш гарантує, що запит був фактично виданий від власника заданої apikey.

Для аутентифікованих запитів (зроблених від імені користувача) я все ще не вирішу між переходом маршруту access_token або комбінованим хешем імені користувача та паролем. Так чи інакше, в якийсь момент буде потрібно комбінація імені користувача / пароля. Тож, коли це станеться, буде використано хеш із кількох відомостей (apikey, apisecret, часова мітка) + пароль. Я хотів би отримати відгуки щодо цього аспекту. FYI, спочатку їм доведеться хеш-пароль, оскільки я не зберігаю паролі у своїй системі без хешування.

Висновок

FYI, це не запит про те, як створити / структурувати API взагалі, лише як керувати автентифікацією та авторизацією виключно в межах програми.

Випадкові думки / бонусні питання

Як для API, які вимагають лише apikey як частину запиту, як ви заважаєте, щоб хтось, крім власника apikey, не міг бачити apikey (оскільки він надсилається в ясні місця) та надсилає надмірні запити, щоб пересувати їх за межі використання? Можливо, я просто замислююся над цим, але чи не повинно бути щось, щоб засвідчити, що запит було підтверджено власником apikey? У моєму випадку, це і було метою апісекрету, він ніколи не показується / передається без хеширования.

Якщо говорити про хеші, що з md5 vs hmac-sha1? Невже це має значення, коли всі значення хешируються досить тривалими даними (наприклад, apisecret)?

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


1
Сподівався отримати ще кілька коментарів / пропозицій. Питання є занадто розпливчастим / неоднозначним?
jsuggs

6
питання ідеально, але навіть майже через 2 роки реалізація oauth здається таємничою ... мені найскладніше досягти саме того, про що ви говорили вище. У мене є додатковий вимір: я не хочу використовувати пару логін-імені / пароля - я хочу використовувати перевірку ідентичності google на android / ios (символ Symbian був оголошений WWF "майже вимерлим видом"), і я відмовляюся розробляти для windows mobile (як би вони цього не називали).
tony gil

8
смішно, що скільки б хто не пропонував oauth 2.0 ive все ж знайти чіткий, простий підручник або приклад, який використовує загальну англійську мову, щоб пояснити кроки, вимоги, завдання та інші дії ...
ChuckKelly

2
Прочитайте цей специфічний потік OAuth2.0 (Потік пароля власника ресурсу). Немає переадресації на веб-сайт. techblog.hybris.com/2012/06/11/…
Франклін

1
Я також шукаю ту саму відповідь. Я знайшов гарну статтю, написану нещодавно. Я сподіваюся, що це допомагає. stormpath.com/blog/the-ultimate-guide-to-mobile-api-security
Новий

Відповіді:


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 + пароль є хешованим, що порушує принцип Керкхоффа і робить його справді небезпечним.
Тамер Шлаш

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
Gary Rowe

9

Twitter вирішив питання зовнішньої програми в oAuth, підтримавши варіант, який вони називають xAuth . На жаль, вже існує безліч інших схем з такою назвою, тому їх можна заплутати незрозуміло.

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

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


2
Я також повинен зазначити, що схоже, що кінцева точка 'пропуску маркера запиту' буде в oAuth 2, вона вказана в поточному проекті як тип дозволу доступу "пароль". Дивіться розділ 4.1.2: tools.ietf.org/html/draft-ietf-oauth-v2-10#section-4.1.2
lantius

Як я вже згадував про Lonra, я дивлюся більше на xAuth і конкретно з причин, про які ви згадали наприкінці ... розробники можуть вам "зняти з полиці" інструменти / lib oAuth для взаємодії з моїм API, що є "хорошою справою" .
jsuggs

6

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

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

У запропонованому рішенні ви зазначаєте, що потрібно буде мінімум три параметри:

  • apikey - надається розробнику при реєстрації
  • мітка часу - являє собою унікальний ідентифікатор для кожного повідомлення для даної apikey
  • хеш - хеш часової позначки + апісекрет

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

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

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

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

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

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