Skip to content

Instantly share code, notes, and snippets.

@nandunbandara
Created October 28, 2018 02:14
Show Gist options
  • Save nandunbandara/06ca41849d846b1cdb1d920cab27f635 to your computer and use it in GitHub Desktop.
Save nandunbandara/06ca41849d846b1cdb1d920cab27f635 to your computer and use it in GitHub Desktop.
Double Submit Cookie Pattern
const
express = require('express'),
bodyParser = require('body-parser'),
cookieParser = require('cookie-parser'),
randomBytes = require('random-bytes'),
app = express(),
// application constants
PORT = 9090,
USERNAME = "demo",
PASSWORD = "pass123$";
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: false}));
app.use(bodyParser.json());
app.use(express.static('public'));
app.listen(PORT, err => {
if(err){
console.error(`ERROR: Can not start server on ${PORT}`);
return;
}
console.log(`SUCCESS: Server started on port ${PORT}`);
});
app.get('/', (req, res) => {
if(req.cookies['csrf-token'] && req.cookies['session-id']){
res.redirect('/form.html');
return;
}
res.redirect('/login.html');
});
// 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 === USERNAME && password === PASSWORD) {
// generate session info
let session_id = Buffer.from(randomBytes.sync(32)).toString('base64');
let csrf_token = Buffer.from(randomBytes.sync(32)).toString('base64');
res.setHeader('Set-Cookie', [
`session-id=${session_id}`,
`csrf-token=${csrf_token}`,
`time=${Date.now()}`
]);
res.sendFile('public/form.html', { root: __dirname });
} else {
res.status(405).json({ success:false, message:"Unauthorized user"});
res.redirect('/');
}
});
app.post('/post', (req, res) => {
let session_id = req.cookies['session-id'];
let csrf_token = req.cookies['csrf-token'];
if(session_id){
// compare csrf tokens in cookies and request body
if(csrf_token === 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 });
}
});
// 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
res.clearCookie('session-id');
res.clearCookie('time');
res.sendFile('public/login.html', { root: __dirname });
});
// explicit calls to routes
app.get('/login', (req, res) => {
const 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 });
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment