1
votes

I have an Express application running on port 3000. The front end runs on port 80, so this is a CORS application. Users are stored in an SQL server database. I'm using passport as the authentication method with Local Strategy as well as express session middleware. The application is a Single page application and all requests sent to server are done via ajax. Users log in on page and the credentials are sent and if authentication is successful, userID as well as username and FullNmae are supposed to be persisted to a session.

I have a lot of things wrong with this: The main thing is that after logging in, express saves the username and other data using passport on to a new session andsends back an html snippet to replace the body tag on the page. However, to test that the user object persists, I call the /create-user route and it says that the user object is not there. Additionally, a new session starts with every request (I check the logs and see that a different session ID is displayed each time). Not only that but at one point I was able to see the session cookie in the browser but I can no longer see it anymore. I tried to go back to the point where I could see the cookie but it still didn't appear!

I've been busting my head for hours and can't figure out why deserializeUser is not called nor why the data is not persisted. Where am I going wrong?

Note: some obvious code ommitted (app.listen(), require statements, etc.)

/* ------ CONFIGURATIONS ------ */
const app = express();
const mssqlConfig = JSON.parse(fs.readFileSync("mssql-config.json", "utf8"));
passport.use(new LocalStrategy(
    function loginAuthentication(username, password, done) {
        let connPool = new mssql.ConnectionPool(mssqlConfig);
        connPool.connect(error => {
            if (error) {console.log(error); return done(error);}
            ps = new mssql.PreparedStatement(connPool);
            ps.input('username', mssql.NVarChar(20));
            ps.input('password', mssql.NVarChar(50));
            ps.prepare('SELECT FullName, fldLoginName, fldEmployeeID, fldPassword FROM tblEmployees WHERE fldLoginName = @username AND fldPassword = @password;', error => {
                if (error) {console.log(error); return done(error);}
                ps.execute({username, password}, (error, result) => {
                    if (error) {console.log(error); return done(error);}
                    console.log(result);
                    if (result.recordset.length == 0) {
                        return done(null, false, {message: "There is no user with those credentials!"});
                    } else if (result.recordset[0].fldLoginName != username || result.recordset[0].fldPassword != password) {
                        return done(null, false, {message: "Username or password is incorrect!"})
                    } else {
                        return done(null, {
                            ID: result.recordset[0].fldEmployeeID,
                            username: result.recordset[0].fldLoginName,
                            fullName: result.recordset[0].FullName
                        });
                    }
                    ps.unprepare(error => console.log(error));
                });
            });
        });
    }
));
passport.serializeUser((user, done) => {
    done(null, JSON.stringify(user));
})
passport.deserializeUser((user, done) => {
    console.log(user);
    done(null, JSON.parse(user));
});

/* ----- MIDDLEWARE ------ */
app.use(function allowCrossDomain(request, response, next) { // CORS
    // intercept OPTIONS method
    response.header('Access-Control-Allow-Credentials', true);
    response.header('Access-Control-Allow-Origin', request.headers.origin);
    response.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    response.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
    response.header('Access-Control-Max-Age', '60');
    if ('OPTIONS' == request.method) {
        response.sendStatus(200);
    } else {
        next();
    }
});
app.use(bodyParser.json());
app.use(session({
    secret:"long string of characters",
    name:'officetools-extensions',
    saveUninitialized:false,
    resave:false,
    cookie:{secure:false, httpOnly:true, maxAge:86400000, domain:"http://officetools-extensions"},
    store: new MemoryStore({checkPeriod:86400000})
}));
app.use(passport.initialize());
app.use(function checkRestrictedURL(request, response, next){
    console.log(request.url);
    if (!request.url.match(/^\/login$/g)) {
        console.log("passed");
        passport.session()(request, response, next);
    } else {
        next();
    }
});

/* ------ ROUTES ------ */
app.post('/login', bodyParser.urlencoded({extended:false}), (request, response, next) => { 
    passport.authenticate('local', {session:true}, (error, user, info) => {
        if (error) { error.status = 500; return next(error); }
        if (info) { let err = new Error(info.message); err.status = 400; return next(err);}
        if (!user) { return response.status(401).send("User could not be logged in!"); }
        console.log(request.sessionID);
        console.log(user);
        console.log(request.session);
        request.logIn(user, function loginCallBack(error) {
            if (error) { error.status = 500; return next(error);}
            console.log("after login", request.session);
            console.log(request.isAuthenticated());
            return response.sendFile(path.join(__dirname + "/templates/barcodes.html"));
        })
    })(request, response, next);
});
app.get("/current-user", (request, response, next) => {
    console.log(request.user, request.session);
    console.log(request.sessionID);
    console.log(request.isAuthenticated());
    if (request.user) { 
        response.header("Content-Type", "application/json");
        return response.send(request.user);
    }
    else { return response.status(401).send("There is no user currently logged in!"); }
});
1

1 Answers

0
votes

I figured it out. I just had to remove the domain property on the session settings. That made it work.