Skip to main content

Session 06: Authentication & Validation

Explain about middleware

https://expressjs.com/en/guide/writing-middleware.html

const express = require('express');
const app = express();

const myLogger = function (req, res, next) {
console.log('LOGGED');
next();
};

app.use(myLogger);

app.get('/', (req, res) => {
res.send('Hello World!');
});

app.listen(3000);

Validation with yup

Install

npm install --save yup

Create a validation schema

  1. Create a folder validations in the root of the project
  2. Create a file validateSchema.js in the validations folder
validations/validateSchema.js
const validateSchema = (schema) => async (req, res, next) => {
try {
await schema.validate({
body: req.body,
query: req.query,
params: req.params,
});
return next();
} catch (err) {
return res.status(400).json({ type: err.name, message: err.message, provider: 'yup' });
}
};

module.exports = {
validateSchema,
};
  1. Create a file schemas.yup.js in the validations folder
validations/schemas.yup.js
const yup = require('yup');

const loginSchema = yup
.object({
body: yup.object({
username: yup.string().email().required(),
password: yup.string().min(3).max(31).required(),
}),
params: yup.object({}),
})
.required();

const registerSchema = yup
.object({
body: yup.object({
username: yup.string().email().required(),
password: yup.string().min(3).max(31).required(),
name: yup.string().min(3).max(31).required(),
email: yup.string().email().required(),
}),
params: yup.object({}),
})
.required();

module.exports = {
loginSchema,
registerSchema,
};

Add validation to middleware of route

  1. Create a route file auth.js in the routes folder
routes/auth.js
const express = require('express');
const router = express.Router();
const { validateSchema } = require('../validations/validateSchema');
const { loginSchema, registerSchema } = require('../validations/schemas.yup');

router.post('/login', validateSchema(loginSchema), function (req, res, next) {
const { email, password } = req.body;

if (email === 'tungnt@softech.vn' && password === '123456789') {
return res.send({ ok: true, name: 'Ngô Thanh Tùng', email, phone: '0905123456' });
}

return res.status(401).send({ ok: false });
});

router.post('/reegister', validateSchema(registerSchema), function (req, res, next) {
const { username, password, name } = req.body;

// Code ...
return res.status(200).send({ ok: true });
});

module.exports = router;

Test with POSTMAN

JWT

Sequence diagram

Flow diagram

Install JWT

npm install --save jsonwebtoken
npm install --save passport
npm install --save passport-jwt
npm install --save passport-http

constants/jwtSettings.js

module.exports = {
SECRET: 'ADB57C459465E3ED43C6C6231E3C9',
AUDIENCE: 'aptech.io',
ISSUER: 'softech.cloud',
};

Config HTTP Basic Authentication in app.js

import

const passport = require('passport');
const BasicStrategy = require('passport-http').BasicStrategy;

Config

passport.use(
new BasicStrategy(async (username, password, done) => {
console.log('🚀 BasicStrategy');

// hard code
if (username === 'aptech' && password === '147258369') {
let error = null;
let user = true;
return done(error, user);
} else {
let error = null;
let user = false;
return done(error, user);
}
}),
);

Use in router: auth.js

// ------------------------------------------------------------------------------------------------
// CALL API HTTP BASIC AUTHENTICATION
// ------------------------------------------------------------------------------------------------
router.get('/basic', passport.authenticate('basic', { session: false }), function (req, res, next) {
res.json({ ok: true });
});

Test with POSTMAN

Config JWT Authentication in app.js

Import

const passport = require('passport');
const JwtStrategy = require('passport-jwt').Strategy;
const ExtractJwt = require('passport-jwt').ExtractJwt;
const jwtSettings = require('./constants/jwtSettings');

Config

// Passport: jwt
const opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = jwtSettings.SECRET;
opts.audience = jwtSettings.AUDIENCE;
opts.issuer = jwtSettings.ISSUER;

passport.use(
new JwtStrategy(opts, function (payload, done) {
console.log(payload);
if (['tungnt@softech.vn', 'peter@gmail.com'].includes(payload.sub)) {
let error = null;
let user = true;
return done(error, user);
} else {
let error = null;
let user = false;
return done(error, user);
}
}),
);

Use in router: auth.js

// ------------------------------------------------------------------------------------------------
// LOGIN WITH JWT + REFRESH TOKEN
// ------------------------------------------------------------------------------------------------
router.post('/jwt', async (req, res, next) => {
const { username, password } = req.body;

if (username === 'tungnt@softech.vn' && password === '123456789') {
// Cấp token
// jwt
const payload = {
message: 'payload',
sub: username,
iat: Date.now(),
};

const secret = jwtSettings.SECRET;

// ACCESS TOKEN
const token = jwt.sign(payload, secret, {
expiresIn: 24 * 60 * 60, //24 * 60 * 60, // expires in 24 hours (24 x 60 x 60)
audience: jwtSettings.AUDIENCE,
issuer: jwtSettings.ISSUER,
subject: username, // Thường dùng để kiểm tra JWT lần sau
algorithm: 'HS512',
});

// REFRESH TOKEN
const refreshToken = jwt.sign({ id }, secret, { expiresIn: '365d' });
res.send({ message: 'Login success!', loggedInUser: found, token, refreshToken });
return;
}

res.status(401).send({ message: 'Login failed!' });
});

Test in router: auth.js

// setup jwt middleware
router.get('/', passport.authenticate('jwt', { session: false }), function (req, res, next) {
res.json({ ok: true });
});

module.exports = router;

Test with POSTMAN