I'm using passport-discord and passport to allow users to authenticate using their discord accounts.
For some reason, cookies aren't being stored in the browser (on frontend website), I use axios (withCredentials set to true in request options) to make a request to my express server which gets the authenticated user from the request (req.user), the session is stored in the database (mongodb atlas), but the cookies aren't being stored in the browser. This works locally, but not when I host the website on a platform like vercel. The cookies are being stored in the API page, but not on the frontend website, which is very weird.
Main file for the api:
const app = require('express')();
const routes = require('./src/routes'); // all the routes
const passport = require('passport');
const mongoose = require('mongoose');
const session = require('express-session');
const cors = require('cors');
const MongoStore = require('connect-mongo');
require('./src/strategies/discord'); // this is where the users are serialized, deserialized
mongoose.connect('database uri');
app.use(
cors({
origin: [
'api url',
'frontend website url',
],
credentials: true,
})
);
app.use(
session({
secret: 'session secret',
cookie: {
maxAge: 30000,
},
resave: false,
saveUninitialized: false,
store: MongoStore.create({
mongoUrl: 'database uri',
}),
})
);
app.use(passport.initialize());
app.use(passport.session());
app.use('/api', routes);
app.listen(3000, () => {
console.log(`[API] Running on Port 3000`);
});
/strategies/discord.js file (where the users are serialized and deserialized:
const passport = require('passport');
const DiscordStrategy = require('passport-discord');
const model = require('../models/User');
passport.serializeUser((user, done) => {
console.log(`Serialized: ${user._id}`);
done(null, user._id);
});
passport.deserializeUser(async (id, done) => {
console.log(`Deserialized: ${id}`)
try {
const user = await model.findById(id);
return user ? done(null, user) : done(null, null);
} catch (err) {
console.log(err);
done(err, null);
}
});
passport.use(
new DiscordStrategy(
{
clientID: 'the client id',
clientSecret: 'the app client secret',
callbackURL: `https://apiurl/discord/redirect`,
scope: ['identify', 'guilds'],
},
async (accessToken, refreshToken, profile, done) => {
const { id, username, discriminator, avatar, guilds } = profile;
try {
const found = await model.findByIdAndUpdate(
id,
{
discordTag: `${username}#${discriminator}`,
avatar,
guilds,
},
{
new: true,
}
);
if (found) {
console.log(`User was found`);
return done(null, found);
} else {
const newUser = await new model({
_id: id,
discordTag: `${username}#${discriminator}`,
avatar,
guilds,
}).save();
return done(null, newUser);
}
} catch (err) {
console.log(err);
return done(err, null);
}
}
)
);
auth.js file (where the users are redirected to the Oauth2 page):
const router = require('express').Router();
const passport = require('passport');
router.get('/discord', passport.authenticate('discord'));
router.get(
'/discord/redirect',
passport.authenticate('discord'),
(req, res) => {
res.redirect(`http://localhost:3001/guilds`);
}
);
router.get('/', (req, res) => {
if (req.user) {
res.send(req.user);
} else {
return res.status(401).send('Unauthorized'); // I make a request to this url with axios from my frontend website (withCredentials set to true, so the cookies can be sent)
}
});
module.exports = router;
As you can see in the auth.js file, the user is redirected to the guilds page on the frontend website, once they're logged in. I make a request to my API again, to get the mutual guilds of the discord.js client and the user, where I check if the user is logged in (req.user exists), and if they are, I send the mutual guilds or just a 401 response and redirect the user back to the home page.
Once I login to the website, I am redirected to the guilds page, then immediately redirected to the home page, when I check the console, there is a 401 response (from the API). When I check the "Applications" tab of my website, there are no cookies, but the API page has the cookies.
I am not sure if this is an issue with my code, or one of the packages I'm using, any help is appreciated.