1. Code
  2. JavaScript
  3. Node

Аутентификация через социальные сети для приложений Node.js при помощи Passport

Простым выходом из ситуации является предоставление пользователям возможности пройти аутентификацию при помощи имеющихся у них аккаунтов в социальных сетях, например: Facebook, Twitter, Google и т.д. В этой статье мы собираемся осуществить как раз это и добавить возможность входа через социальные сети в пример приложения Node.js, созданного в первой части этой серии, посвященной аутентификации. В результате у нас будет возможность пройти аутентификацию за счет наших аккаунтов Facebook и Twitter при помощи промежуточного ПО (* программное обеспечение. Здесь и далее примеч. пер.) Passport.
Scroll to top

Russian (Pусский) translation by AlexBioJS (you can also view the original English article)

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

Простым выходом из ситуации является предоставление пользователям возможности пройти аутентификацию при помощи имеющихся у них аккаунтов в социальных сетях, например: Facebook, Twitter, Google и т.д. В этой статье мы собираемся осуществить как раз это и добавить возможность входа через социальные сети в пример приложения Node.js, созданного в первой части этой серии, посвященной аутентификации. В результате у нас будет возможность пройти аутентификацию за счет наших аккаунтов Facebook и Twitter при помощи промежуточного ПО (* программное обеспечение. Здесь и далее примеч. пер.) Passport.

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

Вход через социальные сети

Для тех, кто не в курсе, возможность входа через  социальные сети является типом Single Sign-on (* технологии единого входа) за счет использования имеющейся информации со сайтов социальных сетей, например: Facebook, Twitter и т.д., что предполагает наличие у пользователей уже созданных аккаунтов.

Возможность входа через социальные сети реализуется главным образом за счет какой-либо схемы аутентификации, например OAuth 2.0. Для подробного ознакомления с разными потоками (* метод получения токена (уникального идентификатора) для авторизации) входа, которые поддерживает OAuth, прочитайте эту статью. Мы отдали предпочтение Passport для реализации возможности входа через социальные сети для нас, поскольку он предоставляет разнообразные модули для множества провайдеров OAuth, будь то Facebook, Twitter, Google, GitHub и т.д. В данной статье мы будем использовать модули passport-facebook и passport-twitter для предоставления возможности входа при помощи имеющихся у пользователей аккаунтов в Facebook или Twitter.

Аутентификация через Facebook

Для того, чтобы сделать возможной аутентификацию через Facebook, нам для начала необходимо создать приложение Facebook при помощи Портала Facebook для разработчиков. Запишите App ID и App Secret и укажите URL-адрес обратного вызова, перейдя в Settings и указав значение в поле Site URL раздела Website для приложения. Также убедитесь, что ввели корректный адрес электронной почты в поле Contact Email. Он необходим для того, чтобы сделать приложение общедоступным.

Далее перейдите в раздел Status & Review (* App Review) и переключите ползунок в положение Yes, чтобы сделать приложение доступным для пользователей. Мы создаем конфигурационный файл (* файл, с данными о предыдущей, текущей или будущей конфигурации системы или приложения), fb.js, для размещения информации о конфигурации приложения, которая будет необходима для подключения к Facebook.

1
// facebook app settings - fb.js
2
module.exports = {
3
  'appID' : '<your_app_identifier>',
4
  'appSecret' : '<your_app_secret>',
5
  'callbackUrl' : 'http://localhost:3000/login/facebook/callback'
6
}

Стратегия входа через Facebook

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

1
passport.use('facebook', new FacebookStrategy({
2
  clientID        : fbConfig.appID,
3
  clientSecret    : fbConfig.appSecret,
4
  callbackURL     : fbConfig.callbackUrl
5
},
6
7
  // facebook will send back the tokens and profile

8
  function(access_token, refresh_token, profile, done) {
9
  // asynchronous

10
	process.nextTick(function() {
11
    
12
	  // find the user in the database based on their facebook id

13
	  User.findOne({ 'id' : profile.id }, function(err, user) {
14
15
	    // if there is an error, stop everything and return that

16
	    // ie an error connecting to the database

17
	    if (err)
18
	      return done(err);
19
20
		  // if the user is found, then log them in

21
	      if (user) {
22
	        return done(null, user); // user found, return that user

23
	      } else {
24
	        // if there is no user found with that facebook id, create them

25
	        var newUser = new User();
26
27
			// set all of the facebook information in our user model

28
	        newUser.fb.id    = profile.id; // set the users facebook id	                

29
	        newUser.fb.access_token = access_token; // we will save the token that facebook provides to the user	                

30
	        newUser.fb.firstName  = profile.name.givenName;
31
	        newUser.fb.lastName = profile.name.familyName; // look at the passport user profile to see how names are returned

32
	        newUser.fb.email = profile.emails[0].value; // facebook can return multiple emails so we'll take the first

33
34
			// save our user to the database

35
	        newUser.save(function(err) {
36
	          if (err)
37
	            throw err;
38
39
	          // if successful, return the new user

40
	          return done(null, newUser);
41
	        });
42
	     } 
43
	  });
44
    });
45
}));

Настройка маршрутов

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

1
// route for facebook authentication and login

2
// different scopes while logging in

3
router.get('/login/facebook', 
4
  passport.authenticate('facebook', { scope : 'email' }
5
));
6
7
// handle the callback after facebook has authenticated the user

8
router.get('/login/facebook/callback',
9
  passport.authenticate('facebook', {
10
    successRedirect : '/home',
11
	failureRedirect : '/'
12
  })
13
);

Страница для входа нашей демоверсии приложения выглядит следующим образом:

Login With Facebook or TwitterLogin With Facebook or TwitterLogin With Facebook or Twitter

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

Facebook Auth - Grant PermissionsFacebook Auth - Grant PermissionsFacebook Auth - Grant Permissions

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

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

Аутентификация через Twitter

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

Для начала вам необходимо создать новое приложение Twitter при помощи интерфейса Управления приложением. Один момент, на который стоит здесь обратить внимание, - это то, что при указании URL обратного вызова Twitter не работает гладко с ним, если в поле для ввода URL обратного вызова указано "localhost". Для преодоления этой трудности при разработке вы могли бы использовать специальный адрес обратной связи, или "127.0.0.1" вместо "localhost". После создания приложения запишите следующие ключ API и секретную информацию в конфигурационный файл таким образом:

1
// twitter app settings - twitter.js

2
module.exports = {
3
    'apikey' : '<your_app_key>',
4
	'apisecret' : '<you_app_secret>',
5
	'callbackUrl' : 'http://127.0.0.1:3000/login/twitter/callback'
6
}

Стратегия входа через Twitter

Стратегия входа через Twitter является экземпляром TwitterStrategy и имеет следующий вид:

1
passport.use('twitter', new TwitterStrategy({
2
    consumerKey     : twitterConfig.apikey,
3
    consumerSecret  : twitterConfig.apisecret,
4
    callbackURL     : twitterConfig.callbackURL
5
  },
6
  function(token, tokenSecret, profile, done) {
7
    // make the code asynchronous

8
    // User.findOne won't fire until we have all our data back from Twitter

9
    process.nextTick(function() { 
10
11
	  User.findOne({ 'twitter.id' : profile.id }, 
12
        function(err, user) {
13
          // if there is an error, stop everything and return that

14
		  // ie an error connecting to the database

15
	      if (err)
16
	        return done(err);
17
18
			// if the user is found then log them in

19
	        if (user) {
20
	           return done(null, user); // user found, return that user

21
	        } else {
22
	           // if there is no user, create them

23
	           var newUser                 = new User();
24
25
			   // set all of the user data that we need

26
	           newUser.twitter.id          = profile.id;
27
	           newUser.twitter.token       = token;
28
	           newUser.twitter.username = profile.username;
29
	           newUser.twitter.displayName = profile.displayName;
30
	           newUser.twitter.lastStatus = profile._json.status.text;
31
32
			   // save our user into the database

33
	           newUser.save(function(err) {
34
	             if (err)
35
	               throw err;
36
	             return done(null, newUser);
37
	           });
38
	        }
39
	     });
40
	  });
41
    })
42
);

Настройка маршрутов

1
// route for twitter authentication and login

2
// different scopes while logging in

3
router.get('/login/twitter',  
4
  passport.authenticate('twitter')
5
);
6
7
// handle the callback after facebook has authenticated the user

8
router.get('/login/twitter/callback',
9
  passport.authenticate('twitter', {
10
	successRedirect : '/twitter',
11
	failureRedirect : '/'
12
  })
13
);
14
15
/* GET Twitter View Page */
16
router.get('/twitter', isAuthenticated, function(req, res){
17
  res.render('twitter', { user: req.user });
18
});

Теперь для того чтобы протестировать приложение, убедитесь, что вы используете http://127.0.0.1: <port> , а не http://localhost: <port>. Как мы упоминали выше, похоже, что возникает проблема при обмене токенами с Twitter, если в качестве имени хоста указано "localhost". При нажатии кнопки Login with Twitter, как и ожидалось, происходит запрос у пользователя разрешения на использование данных аккаунта пользователя Twitter.

Twitter Auth - Grant PermissionsTwitter Auth - Grant PermissionsTwitter Auth - Grant Permissions

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

Заключение

Вот и все!! Мы успешно добавили возможности входа через Facebook и Twitter в наш пример приложения без написания большого количества кода и не связываясь со сложностями, связанными с механизмом аутентификации, передав тяжелую работу Passport. Подобные стратегии входа могут быть написаны для множества провайдеров, поддерживаемых Passport. С кодом для всего приложения можно ознакомиться в этом репозитории git. Если хотите, то можете расширить его возможности и использовать его в ваших собственных проектах.