Xác thực đăng nhập bằng Passport – Twitter
Bài viết này là một phần của series bài viết Xác thực đăng nhập bằng Passport:
Chào mừng tới phần 3 của series Xác thực đăng nhập bằng Passport. Chúng ta sẽ sử dụng nền tảng của ứng dụng chúng ta đã xây dựng từ những bài trước để thêm tính năng xác thực với Facebook. Chúng ta đã một cấu trúc chương trình đầy đủ với các gói thư viện cần dùng, user model, cấu hình ứng dụng và các views.
Chúng ta đã tạo ra một chương trình với cấu trúc khá rõ ràng và ngắn gọn, ở bài này những gì chúng ta phải làm sẽ là tạo một Twitter app, sửa các file sau:
Lưa thông tin cấu hình Twitter app: AppId, Secret | config/auth.js |
Cấu hình Twitter Strategy cho Passport | config/passport.js |
Khởi tạo route | app/routes.js |
Cập nhật view | views/ |
Trong bài không nó rõ các bước tạo một App Twitter, tôi mặc định các bạn đã làm được bước này. Chúng ta sẽ đi thẳng tới việc cấu hình Passport Twitter Strategy.
Xác thực với Twitter sử dụng Passport
Tạo ứng dụng Twitter
Tiến hành khởi tạo một ứng dụng Twitter tại đường dẫn Twitter Developers. Mình nghĩ việc này không quá phức tạp. Chúng ta sẽ cần các thông tin consumer key, consumer secret, và callback URL.
Callback URL: Ứng dụng của chúng ta sử dụng đường dẫn http://localhost:8080/auth/twitter/callback nhưng Twitter không chấp nhận địa chỉ tên miền là localhost, nên chúng ta phải đăng ký callback url là http://127.0.0.1:8080/auth/twitter/callback .
Giờ thêm thông tin về consumer key và consumer secret vào file auth.js để sử dụng cho việc xác thực với Twitter
// config/auth.js module.exports = { 'facebookAuth': { 'clientID': '182734854751xxxx', // App ID của bản 'clientSecret': '7e7b945a5df7c7da047ee5577058xxxx', // App Secret của bạn 'callbackURL': 'http://localhost:8080/auth/facebook/callback' }, 'twitterAuth': { 'consumerKey': 'ieCPgRLTTijLBvHwQs40xxxx', 'consumerSecret': 'IY0bJrhRU9Pn4Rqf8AtDP7iclsSoEHW62OL7f2oln6vLCgxxxx', 'callbackURL': 'http://localhost:8080/auth/twitter/callback' }, 'googleAuth': { 'clientID': 'your-secret-clientID-here', 'clientSecret': 'your-client-secret-here', 'callbackURL': 'http://localhost:8080/auth/google/callback' } };
Cấu hình Twitter Strategy cho Passport config/passport.js
Giờ để ứng dụng của chúng ta có thể sử dụng xác thực của Twitter, chúng ta sẽ phải cấu hình Twitter Strategy. Strategy này sẽ sử dụng xác thực của Twitter và xử lý dữ liệu khi xác thực Twitter thành công.
Chúng ta đã có code cho Local Strategy và Facebook Strategy ở file này, chúng ta sẽ thêm phần Twitter Strategy ở ngay bên dưới.
// config/passport.js // load những thứ chúng ta cần var LocalStrategy = require('passport-local').Strategy; var FacebookStrategy = require('passport-facebook').Strategy; var TwitterStrategy = require('passport-twitter').Strategy; // Lấy thông tin những giá trị auth var configAuth = require('./auth'); // load user model var User = require('../app/models/user'); module.exports = function (passport) { // ========================================================================= // passport session setup ================================================== // ========================================================================= // required for persistent login sessions // passport needs ability to serialize and unserialize users out of session // used to serialize the user for the session passport.serializeUser(function (user, done) { done(null, user.id); }); // used to deserialize the user passport.deserializeUser(function (id, done) { User.findById(id, function (err, user) { done(err, user); }); }); // code for login (use('local-login', new LocalStategy)) // code for signup (use('local-signup', new LocalStategy)) // code for facebook (use('facebook', new FacebookStrategy)) // ========================================================================= // TWITTER ================================================================= // ========================================================================= passport.use(new TwitterStrategy({ consumerKey: configAuth.twitterAuth.consumerKey, consumerSecret: configAuth.twitterAuth.consumerSecret, callbackURL: configAuth.twitterAuth.callbackURL }, function (token, tokenSecret, profile, done) { process.nextTick(function () { // tìm trong db xem có user nào đã sử dụng twitter id này chưa User.findOne({'twitter.id': profile.id}, function (err, user) { if (err) return done(err); // Nếu tìm thấy user, cho họ đăng nhập if (user) { return done(null, user); // user found, return that user } else { // nếu chưa có, tạo mới user var newUser = new User(); // lưu các thông tin cho user newUser.twitter.id = profile.id; newUser.twitter.token = token; newUser.twitter.username = profile.username; newUser.twitter.displayName = profile.displayName; // lưu vào db newUser.save(function (err) { if (err) throw err; // nếu thành công, trả lại user return done(null, newUser); }); } }); }); })); };
Profile: Object chứ thông tin user của dịch vụ(Facebook, Twitter, Google) sẽ có cấu trúc thông tin khác nhau, nhưng Passport đã xử lý về một đối tượng để dễ xử lý user profile doc.
Chúng ta sẽ sử dụng Strategy cho việc xác thực với Twitter và xử lý khi Twitter trả lại thông tin. Chúng ta sẽ lưu thông tin user và chuỗi token để truy cập các dịch vụ của Twitter.
Theo kinh nghiệm của tôi, khi sử dụng Passport với Twitter chúng ta nhận được những thông tin khác nhau. Thông tin cơ bản nhất được Twitter trả lại trông giống thế này:
{ id: '1306682xx', username: 'hoangxxx', displayName: 'Hoang Dinh', photos: [{ value: 'https://pbs.twimg.com/profile_images/805686xxx/IMG_0075_normal.JPG' }] }
Thông tin email: Bạn có thể hỏi tôi sao không thể lấy thông email của tài khoản Twitter. Trong hệ thống của Twitter, tài khoản không thực sự gắn với một email thực như trên Facebook và Google+.
Giờ chúng ta sẽ thiết lập các routes và hiển thị thông tin user ra profile page.
Routes app/routes.js
Giống như với Facebook, chúng ta sẽ cần 2 routes:
- /auth/twitter: Gửi yêu cầu của chúng ta tời Twitter để yêu cầu xác thực.
- /auth/twitter/callback: Twitter gửi lại ứng dụng của chúng ta chuỗi token và thông tin user.
// app/routes.js ... // ===================================== // TWITTER ROUTES ====================== // ===================================== // yêu cầu xác thực bằng twitter app.get('/auth/twitter', passport.authenticate('twitter')); // xử lý sau khi user cho phép xác thực với twitter app.get('/auth/twitter/callback', passport.authenticate('twitter', { successRedirect: '/profile', failureRedirect: '/' })); ...
Routes của chúng ra rất đơn giản. Yêu cầu xác thực và xử lý callback.
Hiển thị thông tin user index.ejs, profile.ejs
Chúng ta đã có các routes, chúng ta chỉ cần cung cấp cho người dùng một cái nút để đăng nhập với Twitter. Tiếp theo, sau khi họ đã xác thực và được chuyên tới trang riêng tư – profile, chúng ta sẽ hiển thị thông tin của user ở đây.
Nút đăng nhập với Twitter
Chúng ta sẽ thêm nút đăng nhập với Twitter vào file views/index.ejs
<!-- views/index.ejs --> ... <a href="/auth/facebook" class="btn btn-primary"><span class="fa fa-facebook"></span> Facebook</a> <a href="/auth/twitter" class="btn btn-info"><span class="fa fa-twitter"></span> Twitter</a> ...
Chúng ta đã có nút để xác thực với Twitter. Khi user click vào nút đó, họ sẽ truy cập tới route /auth/twitter nơi họ sẽ được chuyển tới Twitter Strategy. Họ sẽ gửi tới Twitter một yêu cầu xác thực.
Nếu một user nhấn Cancel, họ sẽ được chuyển về trang chủ. Đó là cài đặt được đặt ở failureRedirect
của route /auth/twitter/callback
. Nếu việc xác thực thành công, thông tin user sẽ được lưu lại và họ được chuyển tới trang /profile .
Trang Profile views/profile.ejs
Cuối cùng chúng ta sẽ hiển thị thông tin user ở trang profile.
Chúng ta có thể thấy user ở trong db:
Giờ chúng ta hiển thị thông tin ra ngoài trang profile:
<!-- views/profile.ejs --> ... <!-- TWITTER INFORMATION --> <div class="col-sm-6"> <div class="well"> <h3 class="text-info"><span class="fa fa-twitter"></span> Twitter</h3> <p> <strong>id</strong>: <%= user.twitter.id %><br> <strong>token</strong>: <%= user.twitter.token %><br> <strong>username</strong>: <%= user.twitter.username %><br> <strong>displayName</strong>: <%= user.twitter.displayName %> </p> </div> </div> ...
Buzz!
Chúng ta đã hoàn thành việc cấu hình ứng dụng xác thực với Twitter: Cấu hình Passport cho Twitter, thêm routesm, xác thực với Twitter và hiển thị thông tin profile của người dùng.
Bài viết tiếp theo chúng ta sẽ tiến hành xây dựng ứng dụng xác thực với Google.