NRM CRUD Service With Authentication Middleware

Hasan Şahin
HardwareAndro
Published in
5 min readOct 26, 2020
Node.Js-Mongo-Redis

Merhabalar, bugünkü yazımda sizlere Node.js ile Redis’i nasıl kullanırız, Jwt Token ile middleware kullanarak basit CRUD işlemlerinin yapıldığı bir yapıyı anlatacağım.

Database olarak MongoDb’yi tercih ettim. Redis ve Mongo için ücretsiz sağladıkları online servislerinden faydalandım. Siteleri üzerinden hızlı bir şekilde giriş yaparak kullanmaya başlayabilirsiniz.

Redis İçin Gerekli Olan Bilgiler
MongoDb İçin Gerekli Adımlar

MongoDb için ‘Create a New Cluster’ dedikten sonra oluşturduğumuz Cluster üzerinden Connection String’imizi bu şekilde alabiliriz. Burada bulunan ‘kullaniciadi’ ve ‘şifreniz’ kısımlarını panelin sol tarafındaki ‘Database Access’ sekmesinden görüntüleyip değiştirebilirsiniz. ‘databaseadi’ ise Cluster kısmında bulunan ‘Collection’ sekmesinden ulaşabilirsiniz.

Örnek Connection String:

mongodb+srv://kullaniciadi:sifreniz@cluster0.rogvo.mongodb.net/databaseadi?retryWrites=true&w=majority

1. Node.Js Kurulumu

  • Node.Js projemizin kurulumu için terminalenpx create-express-api server yazarak generator aracılığıyla api projemizi oluşturuyoruz. Böylece morgan, dotenv, nodemon gibi paketler hazır gelir.
  • MongoDb’yi kullanmak için ise terminale npm i monk @hapi/joiyazarak monk kütüphanesini kuruyoruz. Monk ile beraber ‘joi’ kütüphanesini de kuruyoruz. Böylelikle Create ve Update işlemlerinde aldığımız json verilerine Validate işlemi yapabiliyoruz.
  • Api testleri için VS Code’un kendi eklentilerinden olan Rest Client kullanabilirsiniz.
  • Jwt’yi kullanabilmemiz için terminale npm i jsonwebtoken yazarak jsonwebtoken kütüphanesini kuruyoruz.
  • Son olarak Redis’i kullanabilmemiz için terminalenpm i redis yazarak redis kütüphanesini kuruyoruz.

Hata almanız durumunda dependencies’leri kontrol edip kurabilirsiniz.

Adım 1-) Projemizi geliştirirken Crud işlemlerini yapacağımız Api’nin ve Auth işlemlerini yapacağımız Api’nin portlarını ayırıyoruz. Bunun için ‘package.json’ dosyasında bulunan “scripts” içine

"dev": "nodemon src/index.js","authServer": "nodemon src/app_auth_server/auth.js",

komutlarını ekliyoruz. Bu sayede farklı terminallerenpm run AuthServer veya npm run dev yazarak iki apiyi de çalıştırabiliyoruz.

Adım 2. İkinci işlem olarak oluşturduğumuz MongoDb ve Redis servislerinin bilgilerini tutacağımız .env dosyasını package.json ile aynı dizine oluşturuyoruz.

Örnek .env dosyası

Adım 3-) Başlangıçta oluşturduğumuz servis bilgilerini projemizde kullanmak için tanımlıyoruz. Jwt için bir secret key ihtiyacımız oluyor. Random bir key oluşturmak için yeni bir terminal açıp sırasıyla aşağıdaki komutları yazıyoruz:

node
require('crypto').randomBytes(64).toString('hex')

Son komutu yazdığınızda size uzun bir hex verir. Bunu access token için kullanıp, tekrar oluşturarak refresh token için de oluşturabilirsiniz.

Ek olarak VS Code için kurmuş olduğumuz Rest Api eklentisini kullanmak isteyenler sonu .rest ile bitecek şekilde yeni bir dosya oluşturabilirler. Örnek kullanımlarını ilerleyen kısımlarda göstereceğim.

Oluşturulan dosyaların son halini buradan görebilirsiniz.

2. CRUD Api Servisinin Kullanımı

Başlangıç olarak app.js dosyasını oluşturuyoruz.

Crud işlemleri için kullanacağımız api ve route dosyalarını ‘api’ klasörü altına koyduk. /Api olarak gelen bütün istekleri mainroute.js’ e yönlendiriyoruz.

mainroute.js üzerinden yaptığımız işlemde ise gelen isteklerde bulunan jwt tokenlarını kontrol eden bir middleware tanımlıyoruz. Eğer token geçersizse 401 döndürüyoruz. Burada ek olarak yaptığımız şey jwt tokenın içine koyduğumuz user objesini verify ederken kullanabiliyoruz. İstersek geçerli token olması durumunda onu ‘req.user=user’ diyerek requestin içine koyabiliriz. Böylece gittiği endpointlerde kolay bir şekilde user bilgilerini kullanabiliriz.

Yazdığımız middleware ile istediğimiz endpointleri token kontrol edecek şekilde yönetebiliriz. Bunun için tek yapmamız gereken belirlediğimiz routerların ortasına router.use('/users',authenticateToken,user); yazarak middleware tanımlaması yapmak. Böylece ‘/api/users/’ isteklerine jwt kontrolü tanımlayarak middleware kısmını tamamlamış olduk.

2.1. MongoDB CRUD İşlemleri

Şimdi yapacağımız işlemde ise MongoDb ile crud işlemlerimizi yapacağız.

İlk olarak express, monk ve joi kütüphanelerimizi tanımlıyoruz.

const express = require('express');
const monk = require('monk'); //Mongo Db Driver
const Joi = require('@hapi/joi')
const router=express.Router()

Sonrasında ise monk ile birlikte MongoDb collectionumuza bağlanıyoruz.

const db=monk(process.env.MONGO_URI) // .env dosyasından alıyoruz.
const users=db.get('users') // Get Collection

Joi kütüphanesini kurmamızın sebebi; alıcağımız verilere validation işlemi uygulamak.

Aşağıda gösterildiği gibi kullandığımızda validate yaptığımız json verileri, koşulu sağlamadığı taktirde aktarıldığı nesneye error message bırakır.

const schema=Joi.object({
name: Joi.string().trim().required(),
email: Joi.string().trim().required(),
password: Joi.string().trim().required()});

MongoDb ile standart crud işlemlerini yaptığımızda user.js dosyası aşağıdaki halini alır.

Middleware kullanırken req.user=user yaptığımız için, bütün api requestlerinde req.user ile jwt içine koyduğumuz user nesnesine ulaşabiliyoruz.

3. Authenticate Server — Redis

Şimdi ise Redis ve Token işlemlerini yapacağımız auth servisini hazırlayacağız. Bu işlem için app_auth_server adında bir dizini ve içine auth.js dosyasını oluşturdum. İlk başta belirttiğim gibi package.json içinde tanımladığımız ikinci servisi bu js dosyası üzerinden yönetiyor olacağız. app.js dosyasına farklı olarak ekstra bir işlem yapmıyoruz.

Bu serviste ise 5000 portunu kullanıyoruz. Aynı dizinde api klasörü ve içine auth_api.js dosyasını oluşturduk. Default route olarak auth_api.js ’i tanımlıyoruz. mainroute.js’inden farklı olarak redis tanımlamalarımızı yapıyoruz.

const express = require('express');
const monk = require('monk'); //Mongo Db Driver
const router=express.Router()
//Jwt
const jwt=require('jsonwebtoken')
//Mongodb
const db=monk(process.env.MONGO_URI)
const users=db.get('users') // Get Collection
//Redis
const redisConnection = require('redis')
const redis = redisConnection.createClient({
port : 18901, // replace with your port
host : process.env.REDIS_URI, // replace with your hostanme or IP address
password : process.env.REDIS_PW })

Tanımlamaları yaptıktan sonra redisin bağlantı sağladığından emin olmak için redis.on('connect',function(){console.log('Redis Connected')}); komutunu kullanabilirsiniz.

Login işlemi için gerekli endpoint’imizi hazırlayalım.

Burada ise gelen email ve password ile kayıtlı kullanıcı kontrolünü yapıyoruz. Eğer kullanıcı mevcut ise Access ve Refresh tokenları oluşturuyoruz. Refresh tokenı yenilenmesi gerektiğinde kontrol etmek için redis.set('key','data','EX','time') kodu ile kaydediyoruz.

Oluşturduğumuz token, Redis’te key olarak kaydediliyor. Böylece isteklerden gelen tokenı key olarak arayabiliyoruz.Data olarak ise user nesnesini kaydediyoruz.

‘EX’ komutu ve sonrasında belirttiğimiz süre(saniye) ile rediste ne kadar süre kalacağını belirtmiş oluyoruz. Oluşturulan 2 tokenı kullanıcıya geri gönderiyoruz.

Refresh token endpointi için aşağıdaki kodları yazıyoruz.

Burada ise redis.get komutu ile gelen refresh tokeni key’ler içinde arıyoruz. Başarılı bir şekilde bulması durumunda tokenin geçerliliğini kontrol etmek için jwt.verify fonksiyonunu kullanıyoruz.

Eğer token geçersizse kullanıcıya 401 gönderiyoruz. Geçerli olması durumunda ister token üzerinden user bilgilerini alıp kullanabilir, isterseniz redis.get komutundan gelen value’yi parse ederek kullanabilirsiniz. Aldığımız user nesnesini tekrardan token üretmek için kullanıp, yeni tokeni kullanıcıya geri döndürüyoruz. Böylece 1 hafta süre ile refresh token kullanarak sisteme erişim sağlanabilir hale geliyor.

auth_api.js’in son halini inceleyebilirsiniz.

4. Api Testi

Sıra oluşturduğumuz .rest uzantılı dosyayı kullanmaya geldi. Başlangıç olarak yetkisiz bir get işlemi yapalım.

Yetkisiz Get İşlemi

Login işlemi ile yeni bir token üretiyoruz ve tekrar deniyoruz.

Login İşlemi ile Token Alımı

Görüldüğü gibi verilerimiz başarılı bir şekilde getirildi.

Yetkili Get İşlemi

/refreshToken adresine Refresh Tokenımızı göndererek yeni token alabiliyoruz.

Refresh Token ile Yeni Token Alımı

Okuyan herkese teşekkür ederim. Umarım faydalı olmuştur.

Git Repo: https://github.com/hasansahinnn/Node.Js-MongoDb-Redis_Simple_Api_CRUD_Process_With_Refresh_Token_Auth

--

--