Skip to content

Instantly share code, notes, and snippets.

@nandunbandara
Last active October 28, 2018 01:27
Show Gist options
  • Save nandunbandara/ed1ce35140bd6ce84926db0f82e6a4d1 to your computer and use it in GitHub Desktop.
Save nandunbandara/ed1ce35140bd6ce84926db0f82e6a4d1 to your computer and use it in GitHub Desktop.
Synchronized Token Pattern : NodeJS
const
express = require('express'),
cookieParser = require('cookie-parser'),
randomBytes = require('random-bytes'),
bodyParser = require('body-parser'),
constants = require('./app/constants'),
app = express(),
PORT = 9090;
// middleware
// TODO: set middleware in app/middleware.js
app.use(cookieParser());
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use(express.static('public'));
const SESSION_DATA = {};
// default route : check if a session is active
app.get('/', (req, res) => {
let session_id = req.cookies['session-id'];
if(session_id && SESSION_DATA[session_id]){
res.sendFile('public/form.html', { root: __dirname });
} else {
res.sendFile('public/login.html', { root: __dirname});
}
});
// handle user login and token generation
app.post('/login', (req, res) => {
let username = req.body.username;
let password = req.body.password;
// validate user input
if(username === undefined || username === ""){
res.status(400).json({ success:false, message: "Username undefined"});
return;
}
if(password === undefined || password === ""){
res.status(400).json({ success:false, message: "Password undefined"});
return;
}
if(username === constants.username && password === constants.password){
// generate session info
let session_id = Buffer.from(randomBytes.sync(32)).toString('base64');
let csrf_token = Buffer.from(randomBytes.sync(32)).toString('base64');
// saving session info
SESSION_DATA[session_id] = csrf_token;
res.setHeader('Set-Cookie', [`session-id=${session_id}`, `time=${Date.now()}`]);
res.sendFile('public/form.html', { root: __dirname });
}else {
res.status(405).json({ success:false, message:"Unauthorized user"});
res.redirect('/');
}
})
app.post('/posts', (req, res) => {
let session_id = req.cookies['session-id'];
// check if the token in the request is same as that is stored in the server
if(session_id && SESSION_DATA[session_id]){
if(SESSION_DATA[session_id] === req.body.csrf_token){
res.status(200).json({success:true});
} else {
res.status(400).json({ success:false });
}
} else {
res.sendFile('public/login.html', { root: __dirname });
}
});
// get token
app.get('/tokens', (req, res) => {
let session_id = req.cookies['session-id'];
console.log('cookies: ', req.cookies);
if(session_id && SESSION_DATA[session_id]){
res.status(200).json({ success:true, token: SESSION_DATA[session_id]});
} else {
res.status(400).json({ success:false, message: 'Token unavailable'});
}
})
// logout user from the application
app.post('/logout', (req, res) => {
let session_id = req.cookies['session-id'];
delete SESSION_DATA[session_id]; // remove csrf token from memory
req.clearCookie('session-id');
req.clearCookie('time');
res.sendFile('public/login.html', { root: __dirname });
});
app.listen(PORT, err => {
if(err){
console.log('ERROR: Could not start server on port ', PORT);
return;
}
console.log('SUCCESS: Started server on port ', PORT);
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment