REST API для веб-сайту, який використовує Facebook для автентифікації


86

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

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

Це питання стосується способу автентифікації на нашому веб-сайті з програми / API і розбито на 2 частини:

  1. Яким є правильний спосіб обробки автентифікації REST з API на веб-сайт, який використовує лише Facebook OAuth як метод автентифікації?

Я багато читав і досліджував про стандартні методи автентифікації для REST API. Ми не можемо використовувати такі методи, як Basic Auth. Через HTTPS , оскільки для користувача не існує облікових даних. Що - щось на зразок цього , здається, тільки для перевірки справжності додатків з використанням API.

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

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

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

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


У мене є подібне запитання на stackoverflow.com/questions/30230482/…, яке говорить про деякі з них
JVK

Відповіді:


99

ОНОВЛЕННЯ: див. Нижче

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

КЛІЄНТУ:

  1. Використовуйте API Facebook для входу та отримання коду OAUTH2.
  2. Обміняйте цей код на маркер доступу.
  3. У кожному виклику мого користувацького API я включатиму ідентифікатор користувача Facebook та маркер доступу.

В API (для кожного методу, який вимагає автентифікації користувача):

  1. Зробіть запит на графік / me Facebook, використовуючи маркер доступу зверху.
  2. Переконайтеся, що повернутий ідентифікатор користувача Facebook відповідає ідентифікатору користувача, переданому моєму API зверху.
  3. Якщо термін дії маркера доступу закінчився, потрібне додаткове зв’язок.

Я ще не перевірив це. Як це звучить?

--- Оновлення: 27 липня 2014 року, щоб відповісти на питання ---

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

КЛІЄНТУ:

  1. Використовуйте API Facebook для входу та отримання коду OAUTH2.
  2. Обміняйте цей код на маркер доступу.
  3. Запросити маркер доступу з мого API, включаючи маркер Facebook як параметр

Про API

  1. Отримайте запит на маркер доступу.
  2. Зробіть запит на графік / me Facebook за допомогою маркера доступу до facebook
  3. Переконайтеся, що користувач Facebook існує та відповідає користувачеві в моїй базі даних
  4. Створіть мій власний маркер доступу, збережіть його та поверніть клієнту для використання з цього моменту

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

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

Я виявив, що зберігати секрет FB у мобільному додатку - погана практика. Поради Facebook зберігати їх лише на вашому сервері. developers.facebook.com/docs/opengraph/using-actions/…
Der_Meister

Якщо ми щоразу надсилаємо user_id та access_token на сервер API (як post / get params). Чи створить це діру в безпеці, якщо хтось зможе перехопити з'єднання?
Nathan Do

@NathanDo Використовуйте HTTPS між вашим клієнтом та сервером API, і це не повинно бути проблемою, якщо хтось перехоплює з'єднання (вразливості типу Heartbleed).
dcr

15

Це моя реалізація з використанням JWT (веб-токени JSON), в основному схожа на оновлену відповідь Кріса. Я використовував Facebook JS SDK та JWT.

Ось моя реалізація.

  1. Клієнт: Використовуйте Facebook JS SDK для входу та отримання маркера доступу.

  2. Клієнт: Запитуйте JWT у мого API, викликаючи /verify-access-tokenкінцеву точку.

  3. MyAPI: Отримує маркер доступу, перевіряє його, викликаючи /meкінцеву точку Facebook API.

  4. MyAPI: Якщо маркер доступу є дійсним, знаходить користувача з бази даних, і входить до користувача, якщо такий існує. Створіть JWT із необхідними полями як корисне навантаження, встановіть термін дії, підпишіть секретним ключем і надішліть назад клієнту.

  5. Клієнт: Зберігає JWT у локальному сховищі.

  6. Клієнт: надсилає маркер (JWT з кроку 5) разом із запитом на наступний виклик API.

  7. MyAPI: перевірити маркер секретним ключем, якщо маркер дійсний, обміняти маркер на новий, надіслати його назад клієнту разом із відповіддю API. (Після цього жоден зовнішній API не вимагає перевірки маркера) [якщо маркер недійсний / термін дії минув, клієнт повторно автентифікується і повторить з 1]

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

Кожен маркер використовується один раз.

Прочитайте більше відповідей про безпеку та JWT

Наскільки безпечним є JWT

Якщо ви можете декодувати JWT, як вони захищені?

Веб-маркери JSON (JWT) як маркери ідентифікації та аутентифікації користувачів


3
Думаю, швидше за все має бути №3 /debug_token, щоб ви могли перевірити, чи токен насправді призначений для вашої програми.
Peppe LG

2
Не запитувати access_tokenв Клієнті. Використовуйте "робочий процес коду". Перейдіть codeдо MyAPI і зробіть ще одну поїздку в обидва боки до Facebook, щоб обмінятися codeз нею access_token. Це пояснюється тут більш детально: developers.facebook.com/docs/facebook-login/security
omikron

5

Я намагаюся відповісти на те саме питання, і останнім часом я багато читав ...

У мене не буде відповіді "на", але для мене все стає трохи зрозумілішим. Чи читали ви коментарі до згаданої вами статті ? Я знайшов їх справді цікавими та корисними.

Як результат, і з огляду на те, як все розвивалося з моменту написання першої статті, ось, що я думаю, я зроблю:

  • HTTPS скрізь - це дозволяє забути про HMAC, підписання, nonce, ...

  • Використовуйте OAuth2:

    • Коли запити на автентифікацію надходять із моїх власних програм / веб-сайту, використовуйте цей «фокус» (або його різновид), описаний у відповіді на згадану статтю .

    • У моєму випадку у мене є два типи користувачів: ті, хто має класичні облікові дані для входу / пароля, і ті, хто зареєструвався у Facebook Connect.
      Тож я б запропонував звичайну форму для входу з кнопкою «Увійти через Facebook». Якщо користувач входить зі своїми "класичними" обліковими даними, я просто надсилаю їх на свою кінцеву точку OAuth2 за допомогою grant_type=password.
      Якщо він вирішить увійти через Facebook, я думаю, це буде двохетапний процес:

      • Спочатку використовуйте Facebook iOS SDK, щоб відкрити FBSession
      • Коли це буде зроблено, і програма повернеться під контроль, повинен бути спосіб отримати ідентифікатор Facebook для цього користувача. Я б надіслав цей ідентифікатор окремо до моєї кінцевої точки OAuth2 з наданням розширення, яке мій сервер розуміє як "використання ідентифікатора користувача FB".

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

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

Оновлення
Вхід на Facebook не є рішенням, як зазначено в коментарях: будь-хто міг надіслати довільний ідентифікатор користувача та увійти як цей користувач в API.

А як щодо цього:

  • Покажіть форму входу за допомогою кнопки «Вхід на Facebook»
  • Якщо вибрано цей спосіб входу, поводьтесь подібно до Facebook SDK: відкрийте веб-сторінку з вашого сервера автентифікації, яка ініціює вхід у Facebook.
  • Як тільки користувач увійде в систему, Facebook використає вашу URL-адресу для переадресації для підтвердження; вказати, що ця URL-адреса вказує на іншу кінцеву точку вашого сервера автентифікації (можливо, з додатковим параметром, що вказує, що дзвінок надійшов із програми?)
  • Коли потрапляє кінцева точка автентифікації, автентифікація може надійно ідентифікувати користувача, зберегти його ідентифікатор користувача FB / сеанс FB і повернути маркер доступу до вашого додатку за допомогою власної схеми URL-адрес, як це робить Facebook SDK

Виглядає краще?


1
Дякуємо за відповідь! Я думав про більшість із того, що ви сказали, але головне, що мене хвилювало із використанням FB iOS SDK, а потім надсиланням ідентифікатора користувача Facebook, було те, що нелегко було б надіслати будь-який ідентифікатор, який ви хочете, до вашої кінцевої точки API і заявити, що він є інший користувач? Тут я зазвичай застряю ..
Адам

Справді! Це було по-дурному з моєї точки зору, не думати про це ... Тож рішення має якось пройти ваш власний сервер автентифікації ...
Олів’є Ланс

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