Tag Archives: mongoose

Node.js ile JWT authentication örneği

Kullanılan bağımlılıklar

  • Express: HTTP metodlarını hızlı bir geliştirmemizi sağlayan Node.js framework
  • MongoDB Atlas: https://cloud.mongodb.com/ MongoDB i locale kurmak yerine cloud üzerinden kurulumunun yapılması için
  • Mongoose: MongoDB için Node.js nesne modelleme aracı (Hibernate gibi)
  • Bcrypt: Parola hash için kullanılan node.js kütüphanesi. (https://github.com/kelektiv/node.bcrypt.js) Örnekte parolayı hashlerken random text(SALT) + password şeklinde hash ediliyor.
  • Jsonwebtoken: JWT üretmemizi sağlayacak Node.js kütüphanesi
  • Body-parser: HTTP Request içerisindeki body kısmını alabilmemiz için gerekli modül

MongoDB için cloud.mongodb.com üzerinden bir cluster oluşturulur. IP Whitelist ile sadece kendiniz erişebileceğiniz şekilde ayarlayabilirsiniz yada 0.0.0.0 yaparak herkesin erişmesini sağlayabilirsiniz

Cluster->Connect->Connect your application ile ConnectionString alınır. Network access ile IP Whitelist oluşturulur.
let dbUrl = 'mongodb+srv://SUNUCU_ADI:'+ encodeURIComponent('PAROLA_BURADA') + '@cluster0-vtlge.mongodb.net/test?retryWrites=true&w=majority';
module.exports = {
    mongoURI: dbUrl
};

MongoDB dağıtık ve verileri Document-based(tablosal değil döküman tabanlı key, value gibi) tabanlı bir veritabanıdır. Mongoose ise MongoDB dökümanlarını biraz daha tablosal hale (schema based) getiren nesne modelleme aracıdır. Schema validasyonu, type casting/conversions, model logic gibi işleri kendisi yönetir. CRUD metodları mongoose ile schema ları ile birlikte gelir.

const UserSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  },
  email: {
    type: String,
    required: true
  },
  password: {
    type: String,
    required: true
  },
  date: {
    type: Date,
    default: Date.now
  }
});
const User = mongoose.model('User', UserSchema);
module.exports = User;

Parolayı database e kayıt ederken plain halini değilde hash halini database’e kayıt etmek iyi bir pratiktir. Bcrypt kendi built-in metodları ile otomatik üretilen salt parolayı db ye kayıt eder. Login sırasında compare ederken yine salt kullanılarak hash edilmiş şifreyi kullanıcının şifresi ile kıyaslar.

https://codahale.com/how-to-safely-store-a-password/ —- tl;dr : use bcrypt

router.post('/register', (req, res) => {
  const { name, email, password } = req.body;
  User.findOne({ name })
    .then(user=>  {
      if(user) {return res.status(400).json()}
    });
  const newUser = new User({
    name,
    email,
    password
  });
  bcrypt.hash(password, saltRounds, (err, hash) => {
    newUser.password = hash;
    newUser.save((err, user) => {
      if (err) return console.error(err);
      console.log(user.email);
    });  
  });
  res.send("ok");
});

LogIn ve JWT üretmek/1dakikalık geçerli accessToken

router.get('/authenticate', (req, res) => {
  const {username, password} = req.query;
  User.findOne({name: username}, (err, user) => {
    if(user){
      bcrypt.compare(password, user.password, function(err, result) {
        if(result){
          jwt.sign({id: user.id, email: user.email}, 
            require('../config/default').JWT_SECRET,
            {expiresIn: '60s'},
            (err, token) => {
              return res.json({
                token: token
              });
          });
        }else{
          return res.status(400).json('user or password is incorrect')
        }
      });
    }else{
      return res.status(400).json('user or password is incorrect')
    }
  });
});

API güvenli hale getirmek: Özel bir resource’a request geldiğinde middleware fonksiyonu ile Request header’i içerisinde Authorization eki aranması ve request objesine token set edilmesi. Resource içerisinde ise token verify edilir.

router.get('/profil', verifyToken, (req, res) => {
  jwt.verify(req.token, require('../config/default').JWT_SECRET, (err, userData) => {
    if(err){
      res.sendStatus(403);
    }else{
      res.json({
        userData,
        secret: 'Node is great'
      });
    }
  });
});

function verifyToken(req, res, next){
  const bearerHeader =  req.headers['x-access-token'] || req.headers['authorization'];
  if(typeof bearerHeader !== 'undefined'){
    const bearer = bearerHeader.split(' ');
    const token = bearer[1];
    req.token = token;
    next();
  }else {
    res.sendStatus(403).json('Access denied');
  }
}

Kod: https://github.com/eroltutumlu/node-auth