Статьи

Добавьте социальный вход через Google и Facebook в свое одностраничное приложение

Вход в социальную сеть SPA: аутентифицируйте своих пользователей через Google и Facebook

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

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

Весь исходный код этой статьи доступен для скачивания из нашего репозитория GitHub .

Зачем использовать социальный вход для вашего SPA?

При реализации механизма входа в веб-приложение необходимо учитывать ряд проблем.

  • Как ваш пользовательский интерфейс должен обрабатывать саму аутентификацию?
  • Как хранить информацию о пользователе?
  • Как лучше всего защитить учетные данные пользователя?

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

Многие сайты, в основном социальные сети, позволяют вам использовать их платформы для аутентификации ваших собственных приложений. Это достигается с помощью ряда различных API — OAuth 1.0 , OAuth 2.0 , OpenID , OpenID Connect и т. Д.

Реализация вашего входа в систему с помощью этих социальных технологий входа в систему предлагает ряд преимуществ.

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

Зачем использовать токен-аутентификацию для своего API?

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

  • Сеансовая аутентификация
  • Проверка подлинности на основе файлов cookie
  • Проверка подлинности на основе токенов

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

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

Основанный на токене вариант вариации аутентификации на основе файлов cookie, но предоставляет больше контроля в ваших руках. По сути, вы генерируете токен так же, как в системе аутентификации на основе файлов cookie, но вы включаете его в запросы самостоятельно — обычно в заголовке «Авторизация» или непосредственно в URL-адресе. Это означает, что вы полностью контролируете хранение токена, какие запросы будут включать его и так далее.

Примечание. Несмотря на то, что заголовок HTTP называется «Авторизация», мы фактически выполняем аутентификацию с ним. Это потому, что мы используем его, чтобы выяснить, «кто» является клиентом, а не «что» разрешено делать клиенту.

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

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

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

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

Если вы хотите освежить в памяти информацию об использовании JWT в Node, ознакомьтесь с нашим руководством: Использование веб-токенов JSON с Node.js.

Другим недостатком использования полного токена является размер. Ссылочный токен может быть реализован, например, с использованием UUID, который будет иметь длину 36 символов. И наоборот, JWT может легко содержать сотни символов.

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

Что такое паспорт?

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

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

В этой статье мы будем использовать модули passport-google-oauth , passport-facebook и passport-jwt , что позволит нам реализовать как социальные входы , так и аутентификацию на основе токенов JWT для конечных точек API.

Модуль passport-jwt будет использоваться для того, чтобы требовать, чтобы определенные конечные точки — наши действительные конечные точки API, для доступа к которым требуется аутентификация — имели действительный JWT, присутствующий в запросе. Модули passport-google-oauth и passport-facebook будут использоваться для предоставления конечных точек, которые проходят аутентификацию на Google и Facebook соответственно, а затем генерируют JWT, который можно использовать для доступа к другим конечным точкам в приложении.

Внедрение социальных логинов для одностраничного приложения

Отсюда мы собираемся пройти через тривиальное одностраничное приложение и внедрить в него социальные логины. Это приложение написано с использованием Express, с простым API, обеспечивающим одну защищенную и одну незащищенную конечную точку. Исходный код для этого может быть проверен с https://github.com/sitepoint-editors/social-logins-spa, если вы хотите следовать. Это приложение можно создать, выполнив npm install внутри загруженного исходного кода, чтобы загрузить все зависимости, а затем запустив его, выполнив node src/index.js .

Чтобы успешно использовать приложение, вам необходимо зарегистрироваться для входа в социальные учетные данные в Google и Facebook, а также сделать эти учетные данные доступными для приложения. Полные инструкции доступны в файле README демонстрационного приложения. Они доступны как переменные среды. Таким образом, приложение может быть запущено следующим образом:

 # Linux / OS X $ export GOOGLE_CLIENTID=myGoogleClientId $ export GOOGLE_CLIENTSECRET=myGoogleClientSecret $ export FACEBOOK_CLIENTID=myFacebookClientId $ export FACEBOOK_CLIENTSECRET=myFacebookClientSecret $ node src/index.js 
 # Windows > set GOOGLE_CLIENTID=myGoogleClientId > set GOOGLE_CLIENTSECRET=myGoogleClientSecret > set FACEBOOK_CLIENTID=myFacebookClientId > set FACEBOOK_CLIENTSECRET=myFacebookClientSecret > node src/index.js 

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

JWT являются особенно хорошим выбором для нашего сценария, потому что они полностью самодостаточны и при этом безопасны. JWT состоит из полезной нагрузки JSON и криптографической подписи. Полезная нагрузка содержит информацию о прошедшем проверку пользователе, системе проверки подлинности и периоде действия токена. Затем подпись гарантирует, что она не может быть подделана злонамеренными третьими лицами — только тот, у кого есть ключ подписи, сможет создать токены.

Следуя этой статье, вы увидите частые ссылки на модуль config.js, включенный в состав приложения. Это используется для настройки приложения и использует модуль Node-convict для внешней настройки. Конфигурация, которая используется в этой статье, выглядит следующим образом:

  • http.port — порт, на котором работает приложение. По умолчанию это 3000, и оно переопределяется с помощью переменной среды «PORT».
  • authentication.google.clientId — идентификатор клиента Google, используемый для аутентификации Google. Это предоставляется приложению с помощью переменной среды GOOGLE_CLIENTID
  • authentication.google.clientSecret — секретный ключ клиента Google, используемый для аутентификации Google. Это предоставляется приложению с помощью переменной среды GOOGLE_CLIENTSECRET.
  • authentication.facebook.clientI d — идентификатор клиента Facebook, используемый для аутентификации Facebook. Это предоставляется приложению с помощью переменной среды «FACEBOOK_CLIENTID»
  • authentication.facebook.clientSecret — секретный ключ клиента Facebook, используемый для аутентификации Facebook. Это предоставляется приложению с помощью переменной среды «FACEBOOK_CLIENTSECRET».
  • authentication.token.secret — Секрет, используемый для подписи JWT, используемого для нашего токена аутентификации. По умолчанию это «mySuperSecretKey».
  • authentication.token.issuer — Эмитент, хранящийся в JWT. Это указывает на то, какая служба выпустила токен в тех случаях, когда одна служба аутентификации обслуживает множество приложений.
  • authentication.token.audience — аудитория, хранящаяся внутри JWT. Это указывает на то, для какой службы предназначен токен, в случаях, когда одна служба аутентификации обслуживает множество приложений.

Интегрированный паспорт

Прежде чем использовать его в вашем приложении, необходимо немного настроить Passport. Это всего лишь проверка того, что модуль установлен, и инициализация промежуточного программного обеспечения в вашем приложении Express.

Модуль, который нам нужен для этого этапа — это модуль passport , а затем для установки промежуточного программного обеспечения нам просто нужно добавить его в наше приложение Express.

 // src/index.js const passport = require('passport'); ..... app.use(passport.initialize()); 

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

Реализация аутентификации токена JWT для защищенной конечной точки

Настройка аутентификации токена JWT относительно проста с Passport. Мы будем использовать модуль passport-jwt , который выполняет всю тяжелую работу за нас. Этот модуль ищет заголовок «Authorization», где значение начинается с «JWT», и обрабатывает оставшуюся часть заголовка как токен JWT, используемый для аутентификации. Затем он декодирует JWT и делает хранящиеся в нем значения доступными для вашего собственного кода, которым можно манипулировать — например, для поиска пользователей. Если JWT недействителен, например, если подпись недействительна, токен истек…, тогда запрос будет не аутентифицирован без какого-либо дополнительного участия из вашего собственного кода.

Конфигурирование аутентификации токена JWT в таком случае выполняется следующим образом:

 // src/authentication/jwt.js const passport = require('passport'); const passportJwt = require('passport-jwt'); const config = require('../config'); const users = require('../users'); const jwtOptions = { // Get the JWT from the "Authorization" header. // By default this looks for a "JWT " prefix jwtFromRequest: passportJwt.ExtractJwt.fromAuthHeader(), // The secret that was used to sign the JWT secretOrKey: config.get('authentication.token.secret'), // The issuer stored in the JWT issuer: config.get('authentication.token.issuer'), // The audience stored in the JWT audience: config.get('authentication.token.audience') }; passport.use(new passportJwt.Strategy(jwtOptions, (payload, done) => { const user = users.getUserById(parseInt(payload.sub)); if (user) { return done(null, user, payload); } return done(); })); 

Выше у нас есть пара внутренних модулей, которые мы используем:

  • config.js — содержит наши свойства конфигурации для всего приложения. Можно предположить, что они уже настроены и что значения легко доступны для использования
  • users.js — это пользовательский магазин для приложения. Это позволяет пользователям загружаться и создаваться — здесь мы просто загружаем пользователя по его внутреннему идентификатору.

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

Декодирование токена полностью passport-jwt модулем passport-jwt , и все, что нам нужно сделать, — это предоставить конфигурацию, которая соответствует конфигурации, которая использовалась для генерации токена. Поскольку JWT является стандартом, любые модули, которые следуют стандарту, могут отлично работать вместе.

Когда токен успешно декодируется, он передается в качестве полезной нагрузки нашему обратному вызову. Здесь мы просто пытаемся найти пользователя, идентифицированного «субъектом» из токена. В действительности вы можете сделать дополнительные проверки, например, чтобы убедиться, что токен не был отозван.

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

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

 // src/index.js app.get('/api/secure', // This request must be authenticated using a JWT, or else we will fail passport.authenticate(['jwt'], { session: false }), (req, res) => { res.send('Secure response from ' + JSON.stringify(req.user)); } ); 

Строка 3 выше — это магия, которая заставляет Passport обрабатывать запрос. Это приводит к тому, что Passport запускает стратегию «jwt», которую мы только что настроили для входящего запроса, и либо разрешает его выполнение, либо сразу же завершается неудачей.

Мы можем увидеть это в действии, запустив приложение — выполнив node src/index.js — и попытавшись получить доступ к этому ресурсу:

 $ curl -v http://localhost:3000/api/secure > GET /api/secure HTTP/1.1 > Host: localhost:3000 > User-Agent: curl/7.51.0 > Accept: */* > < HTTP/1.1 401 Unauthorized < X-Powered-By: Express < Date: Tue, 13 Jun 2017 07:53:10 GMT < Connection: keep-alive < Content-Length: 12 < Unauthorized 

Мы не предоставляем заголовок авторизации, и он не позволяет нам продолжить.
Однако если вы предоставите правильный заголовок авторизации, вы получите успешный ответ:

 $ curl -v http://localhost:3000/api/secure -H "Authorization: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0OTczNDAzNzgsImV4cCI6MTQ5NzM0Mzk3OCwiYXVkIjoic29jaWFsLWxvZ2lucy1zcGEiLCJpc3MiOiJzb2NpYWwtbG9naW5zLXNwYSIsInN1YiI6IjAifQ.XlVnG59dX-SykXTJqCmvz_ALvzPW-yGZKOJEGFZ5KUs" > GET /api/secure HTTP/1.1 > Host: localhost:3000 > User-Agent: curl/7.51.0 > Accept: */* > Authorization: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0OTczNDAzNzgsImV4cCI6MTQ5NzM0Mzk3OCwiYXVkIjoic29jaWFsLWxvZ2lucy1zcGEiLCJpc3MiOiJzb2NpYWwtbG9naW5zLXNwYSIsInN1YiI6IjAifQ.XlVnG59dX-SykXTJqCmvz_ALvzPW-yGZKOJEGFZ5KUs > < HTTP/1.1 200 OK < X-Powered-By: Express < Content-Type: text/html; charset=utf-8 < Content-Length: 60 < ETag: W/"3c-2im1YD4hSDFtwS8eVcEUzt3l5XQ" < Date: Tue, 13 Jun 2017 07:54:37 GMT < Connection: keep-alive < Secure response from {"id":0,"name":"Graham","providers":[]} 

Чтобы выполнить этот тест, я вручную сгенерировал JWT, посетив https://www.jsonwebtoken.io и заполнив там форму. «Полезная нагрузка», которую я использовал, была

 { "iat": 1497340378, // Tuesday, 13 June 2017 07:52:58 UTC "exp": 1497343978, // Tuesday, 13 June 2017 08:52:58 UTC "aud": "social-logins-spa", "iss": "social-logins-spa", "sub": "0" } 

А «Ключом подписи» был «mySuperSecretKey», как взято из конфигурации.

Поддержка генерации токенов

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

 // src/token.js const jwt = require('jsonwebtoken'); const config = require('./config'); // Generate an Access Token for the given User ID function generateAccessToken(userId) { // How long will the token be valid for const expiresIn = '1 hour'; // Which service issued the token const issuer = config.get('authentication.token.issuer'); // Which service is the token intended for const audience = config.get('authentication.token.audience'); // The signing key for signing the token const secret = config.get('authentication.token.secret'); const token = jwt.sign({}, secret, { expiresIn: expiresIn, audience: audience, issuer: issuer, subject: userId.toString() }); return token; } 

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

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

Поставщики социальных сетей

Теперь, когда у нас есть возможность генерировать токены, нам нужен способ, чтобы пользователи могли фактически войти в систему. Именно здесь приходят поставщики социальных сетей. Мы добавим возможность перенаправления пользователя к поставщику социальных сетей и Успешно сгенерировать токен JWT и предоставить его движку JavaScript браузера для использования в будущих запросах.
У нас есть почти все элементы для этого, нам просто нужно соединить их вместе.

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

Мы будем открывать эти URL в новом дочернем окне браузера, которое мы сможем закрыть по завершении, и которое сможет вызывать методы JavaScript внутри окна, которое его открыло. Это означает, что процесс является относительно прозрачным для пользователя — в большинстве случаев они увидят новое открытое окно с запросом своих учетных данных, но в лучшем случае они могут не видеть ничего, кроме того, что они вошли в систему.

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

На главной странице JavaScript просто нужно что-то вроде этого:

 // src/public/index.html let accessToken; function authenticate(provider) { window.authenticateCallback = function(token) { accessToken = token; }; window.open('/api/authentication/' + provider + '/start'); } 

При этом в окне регистрируется объект глобальной функции (с именем authenticateCallback ), в котором будет храниться токен доступа, а затем открывается наш маршрут для запуска аутентификации, к которой мы обращаемся в /api/authentication/{provider}/start .

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

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

 <!-- src/public/authenticated.html --> <!DOCTYPE html> <html> <head> <title>Authenticated</title> </head> <body> Authenticated successfully. <script type="text/javascript"> window.opener.authenticateCallback('{{token}}'); window.close(); </script> </body> </html> 

Здесь у нас просто есть немного JavaScript, который вызывает метод authenticateCallback сверху в открывателе этого окна, то есть в главном окне приложения, и затем мы закрываем себя.

На этом этапе токен JWT будет доступен в главном окне приложения для любых целей, которые вы пожелаете.

Реализация аутентификации Google

Аутентификация в Google будет выполняться с помощью модуля passport-google-oauth . Для этого необходимо предоставить три фрагмента информации:

  • ID клиента
  • Секрет клиента
  • URL перенаправления

Идентификатор клиента и его секрет можно получить, зарегистрировав ваше приложение на консоли разработчика Google . URL-адрес перенаправления — это URL-адрес внутри вашего приложения, на который пользователь будет отправлен, когда он вошел в систему со своими учетными данными Google. Это будет зависеть от того, как и где приложение развернуто, но сейчас мы собираемся его жестко закодировать.

Наша конфигурация паспорта для аутентификации Google будет выглядеть следующим образом:

 // src/authentication/google.js const passport = require('passport'); const passportGoogle = require('passport-google-oauth'); const config = require('../config'); const users = require('../users'); const passportConfig = { clientID: config.get('authentication.google.clientId'), clientSecret: config.get('authentication.google.clientSecret'), callbackURL: 'http://localhost:3000/api/authentication/google/redirect' }; if (passportConfig.clientID) { passport.use(new passportGoogle.OAuth2Strategy(passportConfig, function (request, accessToken, refreshToken, profile, done) { // See if this user already exists let user = users.getUserByExternalId('google', profile.id); if (!user) { // They don't, so register them user = users.createUser(profile.displayName, 'google', profile.id); } return done(null, user); })); } 

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

Следующая часть — настроить обработчики маршрутов для управления этим логином. Это будет выглядеть так:

 // src/index.js function generateUserToken(req, res) { const accessToken = token.generateAccessToken(req.user.id); res.render('authenticated.html', { token: accessToken }); } app.get('/api/authentication/google/start', passport.authenticate('google', { session: false, scope: ['openid', 'profile', 'email'] })); app.get('/api/authentication/google/redirect', passport.authenticate('google', { session: false }), generateUserToken); 

Обратите внимание на маршруты для /api/authentication/google/start и /api/authentication/gogle/redirect . Как отмечалось выше, вариант /start — это URL, который мы открываем, а вариант /redirect — это тот, на который Google перенаправляет пользователя в случае успеха. Затем он отображает наше аутентифицированное представление, как показано выше, предоставляя сгенерированный JWT для его использования.

Реализация аутентификации Facebook

Теперь, когда у нас появился наш первый поставщик социальных сетей, давайте расширим и добавим второго. На этот раз это будет Facebook с использованием модуля passport-facebook .

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

Для настройки аутентификации Facebook вам также понадобится идентификатор клиента, секрет клиента и URL-адрес перенаправления.
Идентификатор клиента и секрет клиента (именуемые в Facebook идентификатором приложения и секретом приложения) можно получить, создав приложение Facebook в консоли разработчика Facebook .
Вам нужно будет убедиться, что вы добавили продукт «Facebook Login» в свое приложение, чтобы это работало.

Наша конфигурация паспорта для аутентификации Facebook будет:

 // src/authentication/facebook.js const passport = require('passport'); const passportFacebook = require('passport-facebook'); const config = require('../config'); const users = require('../users'); const passportConfig = { clientID: config.get('authentication.facebook.clientId'), clientSecret: config.get('authentication.facebook.clientSecret'), callbackURL: 'http://localhost:3000/api/authentication/facebook/redirect' }; if (passportConfig.clientID) { passport.use(new passportFacebook.Strategy(passportConfig, function (accessToken, refreshToken, profile, done) { let user = users.getUserByExternalId('facebook', profile.id); if (!user) { user = users.createUser(profile.displayName, 'facebook', profile.id); } return done(null, user); })); } 

Это почти идентично тому, что используется в Google, только вместо термина «facebook». И URL-маршруты похожи:

 // src/index.js app.get('/api/authentication/facebook/start', passport.authenticate('facebook', { session: false })); app.get('/api/authentication/facebook/redirect', passport.authenticate('facebook', { session: false }), generateUserToken); 

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

Резюме

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

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

Эта статья была рецензирована Джеймсом Колсом . Спасибо всем рецензентам SitePoint за то, что сделали контент SitePoint лучшим из возможных