I wrote a JS script for a webserver that includes authentication using the passport and the digest strategy. I am not using sessions, but I have tried using sessions and it does not change the results. The browser requests the "/login" route and displays a built-in login dialog. Authentication works fine, but I can't get the user to "logout." The problem seems to be that the browser remembers the login credentials and resends them automatically. The end result is that the user must close the browser completely to log out, but that is a problem for this application. I know that there must be a way to tell the browser not to do this, but I haven't figured it out.
I figured out a hack to get the browser to display the login dialog again; force the authentication function to return a false. However, I haven't figured out a way to do this per-session. Right now, if one person logs out, everyone gets logged out. It's not a workable solution.
Can anyone tell me what I'm doing wrong here? One thing I'm wondering is whether I'm returning the proper response to the browser when it POSTs to the /logout route (see end). I return res.json(""), but maybe there's a different response I should send to tell the browser to forget the credentials for the session?
My code follows. Any insight is greatly appreciated. Thank you in advance.
T
var passport = require('passport'),
DigestStrategy = require('passport-http').DigestStrategy;
var express = require('express');
var app = express();
app.configure(function () {
app.use(
"/", //the URL throught which you want to access to you static content
express.static('./www') //where your static content is located in your filesystem
);
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.session({ secret: 'keep moving forward' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
});
app.listen(80); //the port you want to use
/**
* CORS support.
*/
app.all('*', function(req, res, next){
if (!req.get('Origin')) return next();
// use "*" here to accept any origin
// For specific domain, do similar: http://localhost'
// Use an array for multiple domains, like [http://localhost', 'http://example.com' ]
res.set('Access-Control-Allow-Origin', '*' );
res.set('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.set('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Authorization');
next();
});
//
// Configure passport authentication
//
// Used to force the browser to display the login screen again.
var forceLogin = false;
passport.use(new DigestStrategy({ qop: 'auth' },
function(username, done ) {
if ( !forceLogin )
{
return done(null, username, "nimda");
}
else
{
//
// Forces the browser to request the user name again by returning a failure to its last request.
//
console.log ( "forcing user to log in" );
forceLogin = false;
return done(null, false);
}
));
passport.serializeUser(function(user, done) {
console.log( "serialize user " + user.toString() );
done(null, user.toString());
});
passport.deserializeUser(function(id, done) {
console.log( "deserialize user " + id.toString() );
done(null, id);
});
app.post('/login', passport.authenticate('digest', { session: true }),
function(req, res) {
console.log( "/login");
res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0');
res.json({ id: req.user.id, username: req.user.username });
});
app.post('/logout', function(req, res){
req.logOut();
// NOTE: Same results as req.logout
//
// req.session.destroy(function (err) {
// res.redirect('/');
// });
res.redirect("/");
// flag to force a login
forceLogin = true;
console.log( "logout");
// Is this the proper return to the browser?
return res.json("");
});
Passport exposes a logout() function on req (also aliased as logOut() ) that can be called from any route handler which needs to terminate a login session. Invoking logout() will remove the req. user property and clear the login session (if any).
Authorization is performed by calling passport. authorize() . If authorization is granted, the result provided by the strategy's verify callback will be assigned to req.account . The existing login session and req.
Passport is very easy to integrate NodeJs package, which is used for adding authentication features to our website or web app.
Passport is Express-compatible authentication middleware for Node. js. Passport's sole purpose is to authenticate requests, which it does through an extensible set of plugins known as strategies.
You could try the following
req.session.destroy()
req.logout()
res.redirect('/')
Saving the new state of the session is important if you're using some form a session store for persistent sessions (eg. Redis). I tried the above code with a similar setup and it seems to work for me
Server needs somehow notify web browser that he need to refresh login info (MD5 digests). For that you can send 401 error code and usually browser will show login popup message.
By the way, all these tricks with sessions are useless because browser already have all required info for automatic logging in.
So you can try next code:
req.logout();
res.send("logged out", 401);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With