Advertisement
  1. Code
  2. Node.js

Автентифікація через соціальні мережі для застосунків Node.js за допомогою Passport

Scroll to top
Read Time: 8 min

Ukrainian (українська мова) 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. За бажанням ви можете розширити його можливості та використати його для власних проектів.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.