Merhabalar,

 

Bu yazıda bir Node.js projesinde en basit haliyle JWT (Json Web Token) kullanımından bahsedeceğim. Örnek olarak hazırladığım projeyi Github üzerinden paylaştığım için çok fazla detaya girmeden, önemli noktalar üzerinde duracağım.

 

Örnek Proje Linki

 

Öncelikle IDE olarak PhpStorm kullandığımı belirtmeliyim. Sağladığı kolaylıklar açısından sizlere de tavsiye ediyorum.

İlk olarak bir Node.js Express App projesi oluşturdum.

 

Sonrasında views klasöründe index.jade, login.jade, register.jade ve data.jade adında 4 adet jade dosyası açarak içeriklerini değiştirdim. İçerikleri burda uzun uzun yazıp sizi sıkmak istemiyorum, Github'daki projeden ulaşabilirsiniz.

 

Terminali açıp gerekli Node.js modüllerini yükledim:

npm install mongoose --save (MongoDB veritabanı için)
npm install jsonwebtoken --save (Json Web Token işlemleri için)
npm install bcryptjs --save (Şifreleme işlemleri için)
npm install cookies --save (Token'ı saklamak için)

 

Veritabanı olarak MongoDB kullanacağım için bu ihtiyacımı mlab sitesinden karşıladım. 500 MB'lik ücretsiz alan avantajını kaçırmak istemedim elbette :) Mlab sitesinde veritabanı nasıl oluşturulur, oluşturulan veritabanına bir kullanıcı nasıl yetkilendirilir vs. bahsetmeyeceğim. Kendi dokümantasyonunda gayet güzel bahsetmişler çünkü :)

 

Projenin kök dizininde db.js adında bir dosya açarak veritabanı bağlantısı işlemlerini ayarladım:

const mongoose = require('mongoose');
module.exports = () => {    
mongoose.connect('mongodb://nodejs-app-with-jwt-user:[email protected]:57538/nodejs-app-with-jwt');    mongoose.connection.on('open', () => {        
  console.log("MongoDB: Connected");    
});    
mongoose.connection.on('error', (err) => {        
  console.log("MongoDB: Error", err);    
});    
mongoose.Promise = global.Promise;};

 

app.js dosyasına giderek db.js dosyasını oyuna dahil ettim:

// DB CONNECTION
const db = require('./db')();

 

Projenin kök dizininde bu defa config.js adında bir dosya oluşturarak içerisine şu kodu yazdım:

module.exports = {    
  api_secret_key: 'çok gizli anahtar'
};

 

Ve yine bu dosyayı da app.js içerisine dahil ederek kullanıma açtım:

// Config
const config = require('./config');
app.set('api_secret_key', config.api_secret_key);

 

Böylelikle api_secret_key adında global bir değişkenim oldu. Bu değişkenin içeriğini istediğiniz gibi düzenleyebilirsiniz.

Yine projenin kök dizininde bu sefer middleware adında bir klasör açtım. İçine de verify-token.js adında bir dosya oluşturdum ve şu şekilde bir kod parçasını dahil ettim:

const jwt = require('jsonwebtoken');
const Cookies = require('cookies');
module.exports = (req, res, next) => {    
  const cookies = new Cookies(req, res);    
  if (cookies.get('x-access-token')) {        
    req.headers['x-access-token'] = cookies.get('x-access-token');    
  }    
  const token = req.headers['x-access-token'] || req.body.token || req.query.token;    
  if (token) {        
    jwt.verify(token, req.app.get('api_secret_key'), (err, decoded) => {            
      if (err) {                
        res.render('error', {error: {status: 'Token hatalı.'}, message: 'Fail Token'});            
      } else {                
        req.decode = decoded;                
        next();            
      }        
    });    
  } else {        
    res.render('error', {error: {status: 'Giriş yapmadan bu sayfayı göremezsiniz.'}, message: 'No Token'});    
}};

 

Ve bir kez daha app.js dosyasına giderek oluşturduğum verify-token.js dosyasını dahil ettim.

// Middleware
const verifyToken = require('./middleware/verify-token');

 

Şu iki satırı da ekleyerek app.js'de ki misyonumu tamamladım:

app.use('/auth', verifyToken);app.use('/auth/data', data);

 

Bu işlemleri yapmakta ki amacım ise şuydu: /auth ile başlayan her türlü linki açma girişiminde eğer giriş yapılmış ve token elde edilmişse verileri göster, giriş yapılmamış ve token elde edilmemiş ise hata ver. Böylelikle verilerimizin bulunduğu /auth/data linkini açmaya çalıştığımızda bu kontrolle karşı karşıya kalacağız.

 

Son olarak register.js ve login.js dosyalarımızın post işlemlerinde neler yapmışım bir bakalım:

 

register.js:

router.post('/', (req, res, next) => {    
  const { email, password } = req.body;    
  bcrypt.hash(password, 10).then((hash) => {        
    const user = new User({           
      email,            
      password: hash        
    });        
    const promise = user.save();        
    promise.then((data) => {            
      res.send('Kayıt başarılı.');        
    }).catch((err) => {            
      res.send('Hata.');        
    });    
  });
});

Bu kod parçası sayesinde register sayfasında email ve password bilgilerini girdiğimde veritabanında ki user tabloma kayıt oluyorum. Tabii ki parolayı şifreli bir şekilde kayıt ediyorum.

 

login.js:

router.post('/', (req, res) => {    
  const { email, password } = req.body;    
  User.findOne({        
    email    
  }, (err, user) => {        
    if (err)            
      throw err;        
    if (!user) {            
      res.send('Kullanıcı bulunamadı.');        
    } else {            
      bcrypt.compare(password, user.password).then((result) => {                
        if (!result) {                    
          res.send('Parola yanlış.');                
        } else {                    
          const payload = {                        
            email                    
          };                    
          const token = jwt.sign(payload, req.app.get('api_secret_key'), {                        
            expiresIn: 720                    
          });                    
          const cookies = new Cookies(req, res);                    
          cookies.set("x-access-token", token, {httpOnly: true}); //secure: true                    
          res.send('1');                
        }            
      });        
   }    
 });
});

Bu kod parçası sayesinde ise login sayfasında girmiş olduğum email ve password bilgilerini veritabanından doğrulayarak sonuç elde ediyorum. Eğer ki bilgiler doğru ise token oluşturup 'x-access-token' olarak cookie'ye ekliyorum. Bu noktada cookie'nin httpOnly ve secure olmasına dikkat edin lütfen. Malum devir kötü, token'ın başına bir şey gelsin istemeyiz :)

 

Evet anlatmak istediklerim bu kadar. Node.js ile yeni yeni haşır neşir olanlar için bu anlattıklarım çok karışık gelmiş olabilir. Ancak projeyi indirip kodları baştan aşağı incelerseniz, bir de çalıştırıp neyin nasıl işlediğine göz atarsanız çok daha anlaşılır hale gelecektir.

 

İyi çalışmalar.