Тут задають багато запитань, і, здається, навіть незважаючи на те, що запитання задаються в контексті Node та passport.js, справжні питання стосуються більше робочого процесу, ніж того, як це зробити за допомогою певної технології.
Давайте скористаємося прикладом налаштування @Keith, трохи зміненим для додаткової безпеки:
- Веб-сервер
https://example.com
обслуговує одну сторінку клієнтської програми Javascript
- Веб-сервіс RESTful у
https://example.com/api
надає серверну підтримку багатим клієнтським додаткам
- Сервер реалізований в Node та passport.js.
- Сервер має базу даних (будь-якого виду) з таблицею "користувачів".
- Ім'я користувача / пароль та Facebook Connect пропонуються як параметри аутентифікації
- Багатий клієнт робить REST-запити
https://example.com/api
- Можуть бути й інші клієнти (наприклад, програми телефону), які використовують веб-сервіс у,
https://example.com/api
але не знають про веб-сервер за адресою https://example.com
.
Зауважте, що я використовую захищений HTTP. На мою думку, це є обов'язковим для будь-якої служби, яка доступна відкрито, оскільки конфіденційна інформація, як паролі та маркери авторизації, передаються між клієнтом та сервером.
Ідентифікація користувача / пароля
Давайте подивимось, як спочатку працює звичайна стара автентифікація.
- Користувач підключається до
https://example.com
- Сервер обслуговує багату програму Javascript, яка надає початкову сторінку. Хтосьбув на сторінці є форма для входу.
- Багато розділів цього додатка для однієї сторінки не заповнені даними через те, що користувач не входив у систему. Усі ці розділи мають слухача подій під час події "входу". Все це на стороні клієнта, сервер не знає про ці події.
- Користувач вводить свій логін та пароль та натискає кнопку подання, яка запускає обробник Javascript для запису імені користувача та пароля у змінні на стороні клієнта. Потім цей обробник запускає подію "входу". Знову ж таки, це все дії клієнта, облікові дані ще не надіслані на сервер .
- Слухачі події "Логін" викликаються. Кожному з них тепер потрібно надіслати один або більше запитів до API RESTful на,
https://example.com/api
щоб отримати конкретні користувачеві дані для візуалізації на сторінці. Кожен окремий запит, який вони надсилають до веб-сервісу, включатиме ім’я користувача та пароль, можливо, у формі автентифікації HTTP Basic , оскільки службі RESTful не дозволяється підтримувати стан клієнта від одного запиту до іншого. Оскільки веб-служба захищена HTTP, пароль надійно шифрується під час транзиту.
- Веб-сервіс
https://example.com/api
отримує купу індивідуальних запитів, кожен з інформацією про автентифікацію. Ім'я користувача та пароль у кожному запиті перевіряються відповідно до бази даних користувачів, і якщо вони виявлені правильними, виконується запитувана функція, а дані повертаються клієнту у форматі JSON. Якщо ім’я користувача та пароль не відповідають помилці, клієнту надсилається помилка у вигляді коду помилки 401 HTTP.
- Замість того, щоб змушувати клієнтів надсилати ім’я користувача та пароль при кожному запиті, ви можете мати функцію "get_access_token" у вашій службі RESTful, яка бере ім'я користувача та пароль та відповідає маркером, який є унікальним криптографічним хешем, який має деякий термін дії дата, пов’язана з нею. Ці маркери зберігаються в базі даних з кожним користувачем. Потім клієнт надсилає маркер доступу в наступних запитах. Токена доступу буде підтверджена відповідно до бази даних замість імені користувача та пароля.
- Клієнтські програми, які не є браузерами, як додатки для телефонів, роблять те саме, що вище, вони просять користувача ввести його / її дані, а потім надсилати їх (або маркер доступу, згенерований з них) з кожним запитом у веб-службу.
Важливим моментом цього прикладу є те, що веб-сервісам RESTful потрібна автентифікація при кожному запиті .
Додатковий рівень безпеки в цьому сценарії додасть авторизацію клієнтських додатків на додаток до автентифікації користувача. Наприклад, якщо у вас є веб-клієнт, додатки iOS та Android, які використовують веб-сервіс, можливо, ви хочете, щоб сервер знав, хто з трьох клієнтів даного запиту, незалежно від того, хто такий користувач, який має автентифікацію. Це може дозволити веб-службі обмежувати певні функції лише певними клієнтами. Для цього ви можете використовувати ключі та секрети API, дивіться цю відповідь для деяких ідей щодо цього.
Аутентифікація у Facebook
Наведений вище робочий процес не працює для підключення до Facebook, оскільки вхід через Facebook має третя сторона, сам Facebook. Процедура входу вимагає перенаправлення користувача на веб-сайт Facebook, де облікові дані вводяться поза нашим контролем.
Тож давайте подивимось, як все змінюється:.
- Користувач підключається до
https://example.com
- Сервер обслуговує багату програму Javascript, яка надає початкову сторінку. Деякі на сторінці є форма для входу, що включає кнопку "Увійти через Facebook".
- Користувач натискає кнопку "Увійти за допомогою Facebook", яка є лише посиланням, на яке перенаправляється (наприклад)
https://example.com/auth/facebook
.
https://example.com/auth/facebook
Маршрут обробляється passport.js (див документації )
- Всі користувачі бачать, що сторінка змінюється, і тепер вони знаходяться на сторінці, розміщеній у Facebook, де їм потрібно увійти та авторизувати нашу веб-програму. Це абсолютно поза нашим контролем.
- Користувач входить у Facebook та надає дозвіл нашому додатку, тому Facebook тепер переспрямовує назад до URL-адреси зворотного виклику, яку ми налаштували в налаштуваннях passport.js, яка за прикладом у документації :
https://example.com/auth/facebook/callback
- Обробник
https://example.com/auth/facebook/callback
маршруту passport.js для маршруту буде викликати функцію зворотного дзвінка, яка отримує маркер доступу від Facebook та деяку інформацію користувача від Facebook, включаючи електронну адресу користувача.
- За допомогою електронного листа ми можемо знайти користувача в нашій базі даних і зберегти в ньому маркер доступу до Facebook.
- Останнє, що ви робите у зворотному дзвінку Facebook, - це перенаправлення назад на багатий клієнтський додаток, але цього разу нам потрібно передати клієнту ім’я користувача та маркер доступу, щоб він міг ним користуватися. Це можна зробити різними способами. Наприклад, змінні Javascript можуть бути додані на сторінку через механізм шаблону на стороні сервера, інакше cookie може бути повернутий з цією інформацією. (дякую @RyanKimber за вказівку на проблеми безпеки при передачі цих даних у URL-адресу, як я спочатку запропонував).
- Отже, ми знову запускаємо додаток на одній сторінці, але клієнт має ім’я користувача та маркер доступу.
- Клієнтська програма може негайно викликати подію "входу" та дозволити різним частинам програми запитувати інформацію, яка їм потрібна, від веб-служби.
- Усі запити, що надсилаються
https://example.com/api
, включатимуть маркер доступу до Facebook для аутентифікації або власний маркер доступу програми, створений з маркера Facebook через функцію "get_access_token" в API REST.
- У додатках, що не входять до браузера, тут це трохи складніше, тому що для входу в систему OAuth потрібен веб-браузер. Щоб увійти з телефону або настільного додатка, вам потрібно буде запустити браузер для переадресації на Facebook, і ще гірше, ви потрібен спосіб, щоб браузер передавав маркер доступу Facebook назад до програми через якийсь механізм.
Я сподіваюся, що це відповість на більшість питань. Звичайно, ви можете замінити Facebook на Twitter, Google або будь-який інший сервіс аутентифікації на базі OAuth.
Мені було б цікаво дізнатися, чи є у когось простіший спосіб вирішити це.
passport-facebook
. Після того, як ви працюєте, наступним кроком є розуміння того, як працює паспорт і як він зберігає облікові дані. Підключення до Restify ( див. Тут оновлену версію тієї, яку ви згадуєте) - це один з останніх кроків (або ви можете реалізувати інтерфейс REST в Express).