I recently set up a node backend using express and integrated Passport for authentication purposes. My application has a route called /login
for logging in and another route called /me
to retrieve information about the currently logged in user.
Below is the code snippet for these routes:
//auth_routes.js
const express = require('express');
const { Users } = require('../database/models');
const router = express.Router();
router.post("/login", async (req, res, next) => {
try {
const user = await Users.findOne({ where: { email: req.body.email } });
if (!user) {
res.status(401).send("Incorrect username and/or password");
}
else if (!await user.correctPassword(req.body.password)) {
res.status(401).send("Incorrect username and/or password");
}
else {
console.log("LOGIN", req.sessionID)
req.login(user, err => {
(err ? next(err) : res.json(user))
});
}
}
catch (err) {
next(err);
}
});
router.get('/me', (req,res) => {
console.log("ME SESSION", req.sessionID)
if (req.user) {
res.json(req.user);
} else {
res.status(401).send("Not logged in");
}
});
module.exports = router;
This is how I initialize passport:
const express = require('express')
const cors = require('cors')
const morgan = require('morgan')
const passport = require('passport')
const bodyParser = require('body-parser')
const session = require('express-session')
const db = require('./database')
const api_routes = require('./routes/api_routes')
const SequelizeStore = require('connect-session-sequelize')(session.Store)
const sessionStore = new SequelizeStore({ db })
const app = express()
const PORT = process.env.PORT || 5000
passport.serializeUser((user,done) => {
console.log("in serialize", user.id)
return done(null,user.id);
});
passport.deserializeUser(async (id,done) => {
console.log("in deserialize", id)
try {
const user = await db.models.Users.findByPk(id);
done(null,user);
} catch (err) {
done(err);
}
});
const configureApp = () => {
app.use(cors({origin:'http://localhost:3001',credentials: true}));
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Origin, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version, X-Response-Time, X-PINGOTHER, X-CSRF-Token,Authorization');
if (req.method === "OPTIONS") {
return res.status(200).end();
} else {
next();
}
});
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: true}))
app.use(morgan('dev'))
app.use(
session({
secret: process.env.SECRET || "SUPER SECRET",
resave: false,
saveUninitialized: false,
store: sessionStore,
cookie: {secure: false}
})
)
app.use(passport.initialize())
app.use(passport.session())
app.use('/api', api_routes)
app.use((err, req, res, next) => {
console.error(err);
console.error(err.stack);
res.status(err.status || 500).send(err.message || "Internal server error");
})
}
const startListening = () => {
app.listen(PORT, () => console.log(`Listening on PORT ${PORT}`))
}
const syncdb = async () => {
await db.sync({force: true});
}
const bootApp = async () => {
await sessionStore.sync();
await syncdb();
await configureApp();
await startListening();
}
bootApp();
My observation so far indicates that when I use Postman to send the post request to /login
and the get request to /me
, everything functions as expected with matching session IDs. However, upon testing from the frontend, users are successfully logged in but encounter a 401 error during the subsequent get request to /me
. Additionally, the session IDs differ between the login request and the me request.
Here's some of my client-side code implemented with Redux and Axios:
export const login = login => async dispatch => {
try {
let { data } = await axios.post('http://lacolhost.com:5000/api/auth/login', login);
console.log(data);
dispatch({type: 'SAVE_RESPONSE', payload: data});
} catch (err) {
console.error("Error logging in", err);
dispatch({ type: 'SAVE_RESPONSE', payload: { message: 'Error communicating with server' }});
}
export const getUser = () => async (dispatch) => {
try {
const { data } = await axios.get('http://lacolhost.com:5000/api/auth/me', {withCredentials: true})
dispatch({
type: 'SELECT_USER',
payload: data
})
} catch (err) {
console.log(err);
}
}
If anyone has insights into what might be causing this discrepancy and how it can be resolved, I would greatly appreciate your assistance. Thank you!