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("");
});