Search This Blog

2023/04/23

pasport.js implement jwt strategy

first install
npm install - g express - generator

then

express--view = ejs apiStack

then install sequelize, passport, passport - jwt & dotenv

create.env file in root directory

add following content to.env file

MYSQL_USER_NAME = root
MYSQL_PASSWORD = "sangram#81"
MYSQL_PORT = 3306
MYSQL_DATABASE = AppDb
MYSQL_HOST = localhost
SECRET_KEY = abcd1234

create Auth folder in root and add auth.js into it

Auth/auth.js

const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const User = require('../models/').User;
const bcrypt = require("bcrypt");

var passportJWT = require("passport-jwt");
var ExtractJwt = passportJWT.ExtractJwt;
var JwtStrategy = passportJWT.Strategy;

var jwtOptions = {}
jwtOptions.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
jwtOptions.secretOrKey = process.env.SECRET_KEY

var strategy = new JwtStrategy(jwtOptions, function (jwt_payload, next) {
console.log('payload received', jwt_payload);
var user = User.findOne({
where: { id: jwt_payload.id }
})
if (user) {
next(null, user);
} else {
next(null, false);
}
});

passport.use(strategy);


create a folder models add into it add index.js & user.js

models / user.js

const sequelize = require('../utils/database')
const bcrypt = require("bcrypt");

module.exports = function (sequelize, DataTypes) {
const User = sequelize.define('User', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
firstName: {
type: DataTypes.STRING,
field: 'firstName'
},
lastName: {
type: DataTypes.STRING,
field: 'lastName'
},
email: DataTypes.STRING,
password: DataTypes.STRING
}, {
freezeTableName: true,
hooks: {
beforeCreate: async (user, options) => {
user.password = await bcrypt.hash(user.password, bcrypt.genSaltSync(8))
}
},
classMethods: {

},
instanceMethods: {
generateHash(password) {
return bcrypt.hash(password, bcrypt.genSaltSync(8))
}
}
});
return User;
}

models / index.js

var fs = require('fs');
var path = require('path');
var Sequelize = require('sequelize');
var sequelize = require('../utils/database')
const { it } = require('node:test')
var basename = path.basename(__filename);
var db = {};

fs.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
var model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes)
db[model.name] = model;
});

Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;


create utils folder in root and add database.js into it

utils / database.js

const Sequelize = require('sequelize')
const sequelize = new Sequelize(
process.env.MYSQL_DATABASE,
process.env.MYSQL_USER_NAME,
process.env.MYSQL_PASSWORD, {
dialect: 'mysql',
host: process.env.MYSQL_HOST
}
);

console.log("process.env.MYSQL_DATABASE", process.env.MYSQL_DATABASE)

sequelize
.authenticate()
.then(() => {
console.log('Connection has been established successfully.');
})
.catch(err => {
console.error('Unable to connect to the database:', err);
});


module.exports = sequelize


update routes / users.js

var express = require('express');
var router = express.Router();
var db = require('../models')
var passport = require('passport');
const bcrypt = require("bcrypt");
var jwt = require('jsonwebtoken');


router.post('/signin', async function (req, res, next) {
var email = req.body.email;
var password = req.body.password;
var firstName = req.body.firstName;
var lastName = req.body.lastName;

if (!req.body.email || !req.body.password) {
res.status(400).send({
msg: 'Please enter email and password.'
});
} else {
try {
let user = await db.User.create({
email: req.body.email,
password: req.body.password,
firstName: req.body.firstName,
lastName: req.body.lastName
})

var returnValue = JSON.parse(JSON.stringify(user))
delete returnValue.password;

res.status(201).send({
msg: 'User created successfully',
data: returnValue
});

} catch (exp) {
console.log("Error", exp)
res.status(201).send({
msg: 'Error Occured while creating User:' + exp.toString()
});
}

}


});

router.post("/login", async function (req, res) {
if (req.body.email && req.body.password) {
var email = req.body.email
var password = req.body.password;
}
// usually this would be a database call:
var user = await db.User.findOne({
where: { email: email }
})

if (!user) {
res.status(401).json({ message: "no such user found" });
}

var re = await bcrypt.compare(req.body.password, user.password)
if (re) {
var payload = { id: user.id };
var token = jwt.sign(payload, process.env.SECRET_KEY);
res.json({ message: "ok", token: token });
} else {
res.status(401).json({ message: "passwords did not match" });
}
});

router.get("/secret", passport.authenticate('jwt', { session: false }), function (req, res) {
res.json("Success! You can not see this without a token");
});


In bin/www

ad top add
const dotenv = require('dotenv');
dotenv.config()

below require http add

const sequelize = require('../utils/database')
var models = require('../models');
const { token } = require('morgan')

console.log("Calling sequelize.sync")
sequelize
.sync()
.then((result) => {
console.log("Sync Done");
})
.catch((err) => {
console.log("Sync Failed", err);
});


in app.js in root folder


after
var app = express();


add

require('./Auth/auth')

app.use(passport.initialize());//initializes passport configuration

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

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


Now we are ready

first signin
POST localhost:3000/users/signin
Body:

{
"firstName":"sangram",
"lastName":"desai",
"email":"ssd1110@gmail.com",
"password":"sangram#81"
}

New user is created in database.

Hit login

POST localhost:3000/users/login
Body:
{
"email":"ssd1110@gmail.com",
"password":"sangram#81"
}

Output:
{
"message": "ok",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNjgyMjM0NTA0fQ.hZC7AiMpNDIccet-kuIaX1GZvw-yD6WbSpcMc8ncxSk"
}

we got jwt token


now we can hit our secret api using this token

GET localhost:3000/users/secret
HEADER:

Authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNjgyMjM0NTA0fQ.hZC7AiMpNDIccet-kuIaX1GZvw-yD6WbSpcMc8ncxSk

Result:
"Success! You can not see this without a token"

Code can be found at:https://github.com/gitsangramdesai/passport.js.jwt

No comments:

Post a Comment