Authentication in NodeJS

passport.jpg

Authentication là một phần không thể thiếu trong mỗi ứng dụng, và với NodeJs cũng thế.

Là một newbie NodeJS, mình cũng thường tìm những modules, packages được cộng đồng sử dụng nhiều nhất để áp dụng vào trong dự án. Với xác thực người dùng trong nodejs mình sẽ giới thiệu cho các bạn một module khá phổ biến đó là Passport.

1. Passport là gì ?

Passport.js một trong những module phổ biến nhất của Nodejs giúp bạn authentication . Nó được thiết kế là một middleware hết sức linh hoạt cho bạn khả năng tùy biến cao với rất nhiều các kịch bản authentication: bạn có thể xác thực qua thông tin người dùng đăng ký trước đó trong database, hoặc với Facebook, G+, Twitter . Bạn cũng có thể tùy biến chính xác các route nào cần phải authentication.

2. Làm thế nào để config passport trong ứng dụng

Mình khá thích thú với NodeJs đó là việc cài đặt các module rất đơn giản và passport cũng thế bạn chỉ cần chạy lệnh bên dưới để download module về

npm install passport

Để sử dụng được passport bạn có vài bước để gọi cá modules vào ứng dụng : Thiết lập route sử dụng middleware:

router.route('/login')
    .get(function (req, res) {
        res.render('login', {
            'title': 'Log in'
        })
    })
    .post('/login', passport.authenticate('local', { successRedirect: '/', failureRedirect:'/login' }));

Require thằng passport và chèn 2 thằng middile của nó vào express là passport.initialize() và passport.session(). Chú ý là ứng dụng express của bạn cần sử dụng đến express-session.

var app = require('express')();
var session = require('express-session');
var bodyParser = require('body-parser');
var passport = require('passport');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

app.use(session({
  secret : "secret",
  saveUninitialized: true,
  resave: true
}))

app.use(passport.initialize());
app.use(passport.session());

Tiếp đến các bạn cần cấu hình cho kịch bản cho passport trong hàm serializeUser() và deserializeUser()

var LocalStrategy = require('passport-local').Strategy;
var passport = require('passport');
var bcrypt = require('bcrypt');

passport.serializeUser(function(user, done) {
    done(null, user.id);
});

passport.deserializeUser(function(id, done) {
    db.user.findById(id).then(function (user) {
        done(null, user);
    }).catch(function (err) {
        console.log(err);
    })
});

passport.use(new LocalStrategy(
    function (username, password, done) {
        db.user.find({where : {
            username : username
        }}).then(function (user) {
            bcrypt.compare(password, user.password, function (err, result) {
                if (err) { return done(err); }
                if(!result) {
                    return done(null, false, { message: 'Sai thông tin username hoặc password' });
                }
                return done(null, user);
            })
        }).catch (function (err) {
            return done(err);
        })
    }
))

Khi user submit form login, một request POST được tạo ra tới route /login , nó sẽ chạy passport.authenticate() .Ở trên ta thiết lập kịch bản Local cho thằng passport.authenticate nên nó sẽ gọi đến cái kịch bản ta đã cài đặt.

Passport sé lấy data từ req.body.username và req.body.passport rồi gán cho hàm verify local. Ở đây như cấu hình ở trên ta thấy chúng ta sẽ query database rồi kiểm tra xem passport của người dùng đưa lên có đúng không.Trong trường hợp Error từ db ta gọi đến callback là done với param là err(done(err)). Khi mà nó không tìm thấy được người dùng hợp lý ta gọi đến thằng done(null,false). Còn nếu thông tin đăng nhập đúng ta gọi done(null, user). Khi callback done được gọi, nó sẽ lấy dữ liệu err, user và dữ liệu bạn custom thêm nếu có trả lại cho thằng passport.authenticate().

Trường hợp dữ liệu trả về của callback là null, true, xác thực thành công passport tiếp tục gọi hàm req.login

Hàm req.login gọi đến thằng passport.serializeUser mà mình đã định nghĩa trước đó. Hàm này truy cập vào đối tượng user mà ta trả về cho middleware passport. Authenticate và xác định xem thành phần nào của đối tượng sẽ lưu vào trong session. Kết quả của hàm này là ta sẽ có đối tượng req.session.passport.user = các thông tin ta truyền vào trong serializeUser.

Xác thực kết thục, function requestHandler sẽ được gọi đưa chúng tra đến trang chủ. Bài viết được mình viết với layout của một newbie nên mình rất mong nhận được nhận xét và chia sẻ của các bạn.

3. Tài liệu tham khảo

All Rights Reserved