Session 06: Authentication & Validation
Explain about middleware
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
- Create a folder
validations
in the root of the project - Create a file
validateSchema.js
in thevalidations
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,
};
- Create a file
schemas.yup.js
in thevalidations
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
- Create a route file
auth.js
in theroutes
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
- Url: http://localhost:3000/auth/basic
- Headers: Authorization
- Type: Basic Auth
- Username: aptech
- Password: 147258369
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;