I have created a basic login page ,after successful login ,the user is redirected to to success page . In the success page their is an a tag which redirects to /logout via get request and destroy the session and redirects to home page . My question is that if a user has opened 2 instances of the application and did logout from one tab then another instanace(tab) is working normally until i refresh the page then it shows forbidden . So what can i do to achive the logout from both the tabs simontaniously like facebook or amazon does here is the code :
const express = require('express');
const url= require('url');
const db=require('./dao.js');
var bodyParser = require('body-parser')
const session = require("express-session");
const app= express();
const nunjucks=require("nunjucks");
const path = require('path');
const Pin=require('./models/pin');
const User=require('./models/users');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.resolve(__dirname,'public')));
nunjucks.configure(path.resolve(__dirname,'views'),{
express:app,
autoscape:true,
noCache:false,
watch:true
});
app.use(session({
secret: "session",
resave: false,
saveUninitialized: true,
cookie: { secure: false }
}));
//passoprt consfig
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (user, next) {
next(null, user);
});
passport.use('local', new LocalStrategy((username, password, done) => {
User.findOne({ username: username }, (err, user) => {
if (err) { return done(err); }
if (!user) { return done(null, null, { message: 'No user found!' }); }
if (user.password !== password) {
return done(null, null, { message: 'Username or password is incorrect!' });
}
return done(null, user, null);
});
}
));
function isAuthenticated(req, res, next) {
if (req.isAuthenticated()) {
next();
} else {
req.session.destroy();
res.status(403).send('Forbidden');
}
}
app.get("/",(req,res)=>{
console.log("hi");
res.render("validate.html",{});
});
app.post('/login', (req, res) => {
// passport.authenticate('local', { successRedirect: '/admin', failureRedirect: '/login' }
passport.authenticate('local', function (err, user, info) {
// console.log(err,user,info);
if (err) {
res.render('validate.html', { error: err });
} else if (!user) {
res.render('validate.html', { errorMessage: info.message });
} else {
//setting users in session
req.logIn(user, function (err) {
if (err) {
res.render('/', { error: err });
} else {
res.redirect('/success');
}
})
}
})(req, res);
});
app.get('/success',isAuthenticated,(req,res)=>{
res.render("index.html",{});
})
app.get("/logout", function (req, res) {
req.session.destroy();
res.redirect('/');
});
app.get("/pincode",(req,res)=>{
console.log(req.query.pincode);
let pin=req.query.pincode;
let pattern= /^[0-9]*$/;
if(pattern.test(pin)){
Pin.find({pincode:pin},(err,data)=>{
if(err)
{
console.log("error");
}
else
{
console.log(data);
//res.render('index.html',{data:data});
res.status(200).send(data);
//res.status(200).json(data);
}
});
}
else{
res.status(200).send("Nan");
//res.render('index.html',{nomessage:"Not a no"});
}
// res.redirect('http://google.com');
});
app.listen(80,()=>{
console.log("App running at port 80");
});
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css" integrity="sha512-1PKOgIY59xJ8Co8+NE6FZ+LOAZKjy+KY8iq0G4B3CyeY6wYHN3yt9PW0XpSriVlkMXe40PTKnXrLnZ9+fkDaog==" crossorigin="anonymous" />
<link rel="stylesheet" href="css/style.css">
<title>Hello, world!</title>
</head>
<body>
<div class="div1">
<div class="container-sm">
<div class="row">
<form action="/login" method="POST" class="col-12" id=form autocomplete="off">
<p class="text-danger">{{message}}</p>
<p class="text-danger">{{error}}</p>
<p class="text-danger">{{errorMessage}}</p>
<input type="text" name="username" id="pin" placeholder="enter email" >
<input type="password" name="password" placeholder="enter passowrd">
<button type="submit" id=btn>login</button>
</form>
</div>
</div>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
<!-- begin snippet: js hide: false console: true babel: false -->
This blog might help,
https://hasura.io/blog/best-practices-of-using-jwt-with-graphql/
Based on the blog,
What will happen if I am logged in on different tabs?
One way of solving this is by introducing a global event listener on localstorage. Whenever we update this logout key in localstorage on one tab, the listener will fire on the other tabs and trigger a "logout" too and redirect users to the login screen.
window.addEventListener('storage', this.syncLogout)
//....
syncLogout (event) {
if (event.key === 'logout') {
console.log('logged out from storage!')
Router.push('/login')
}
}
These are the 2 things we now need to do on logout:
Nullify the token Set logout item in local storage
async function logout () {
inMemoryToken = null;
const url = 'http://localhost:3010/auth/logout'
const response = await fetch(url, {
method: 'POST',
credentials: 'include',
})
// to support logging out from all windows
window.localStorage.setItem('logout', Date.now())
}
view rawlogout2.js hosted with ❤ by GitHub
In that case whenever you log out from one tab, event listener will fire in all other tabs and redirect them to login screen.