I’m making a website with dashboard for a Discord bot. Only when I’m making the authorization page with the help of JWT to make a token it keeps giving me a headers error (see below). I’ll put my code for that specific item under here. I can’t seem to find any resource for why said error pops up.
So ive tried to debug the whole code, when i do so i added console.logs to specific events happening. All of those events returned a (expected) result but only 1 event didn’t. This being adding the cookie to the browser of the individual and redirecting them towards a localhost:5173 (testing this locally before uploading to a website)
Code:
const express = require('express');
const User = require('../../models/User');
const jwt = require('jsonwebtoken');
const router = express.Router();
// GET: api.tick-it.com/auth/signin
// GET: api.tick-it.com/auth/callback
const DASHBOARD_URL = 'http://localhost:5173';
router.get('/signin', (req, res) => {
res.redirect(
`https://discord.com/oauth2/authorize?client_id=${process.env.DISCORD_CLIENT_ID}&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A3001%2Fauth%2Fcallback&scope=guilds+identify`
);
});
router.get('/callback', async (req, res) => {
const DISCORD_ENDPOINT = 'https://discord.com/api/v10';
const CLIENT_ID = process.env.DISCORD_CLIENT_ID;
const CLIENT_SECRET = process.env.DISCORD_CLIENT_SECRET;
const REDIRECT_URI = process.env.DISCORD_REDIRECT_URI;
const DASHBOARD_URL = process.env.DASHBOARD_URL;
const { code } = req.query;
console.log('awaiting code to be checked');
if (!code) {
return res.status(400).json({
error: 'A "code" query parameter must be present in the URL.',
});
}
try {
const oauthRes = await fetch(`${DISCORD_ENDPOINT}/oauth2/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
grant_type: 'authorization_code',
redirect_uri: REDIRECT_URI,
code,
}).toString(),
});
console.log('awaiting oauthResponse.ok');
if (!oauthRes.ok) {
return res.status(500).json({
error: 'Failed to obtain OAuth token.',
});
}
const oauthResJson = await oauthRes.json();
console.log('awaiting @me');
const userRes = await fetch(`${DISCORD_ENDPOINT}/users/@me`, {
method: 'GET',
headers: {
Authorization: `Bearer ${oauthResJson.access_token}`,
},
});
console.log('awaiting userResponse.ok');
if (!userRes.ok) {
return res.status(500).json({
error: 'Failed to fetch user data.',
});
}
const userResJson = await userRes.json();
let user = await User.findOne({ id: userResJson.id });
console.log('awaiting user to be found and added');
if (!user) {
user = new User({
id: userResJson.id,
username: userResJson.username,
avatarHash: userResJson.avatar,
accessToken: oauthResJson.access_token,
refreshToken: oauthResJson.refresh_token,
});
} else {
user.username = userResJson.username;
user.avatarHash = userResJson.avatar;
user.accessToken = oauthResJson.access_token;
user.refreshToken = oauthResJson.refresh_token;
}
await user.save();
const token = jwt.sign(
{
id: userResJson.id,
username: userResJson.username,
avatarHash: userResJson.avatar,
},
process.env.JWT_SECRET,
{ expiresIn: '7d' }
);
console.log('awaiting token to be added')
return someFunction(req, res, token);
// res.cookie('access_token', token, {
// httpOnly: true,
// secure: process.env.NODE_ENV === 'production',
// maxAge: 6.048e8,
// });
// console.log('token added to browser');
// res.redirect(DASHBOARD_URL);
} catch (error) {
console.error(error);
return res.status(500).json({
error: 'Internal Server Error.',
});
}
});
router.get('/signout', (req, res) => {
res.clearCookie('token').sendStatus(200);
});
const someFunction = (req, res, token) => {
try {
res.cookie('access_token', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
maxAge: 6.048e8, // 7 days
});
console.log('Token added to browser');
// Redirect the user to the dashboard
res.redirect(DASHBOARD_URL);
} catch (error) {
// Error handling
console.error('Error occurred:', error);
if (!res.headersSent) {
res.status(500).send('An error occurred');
}
}
};
module.exports = router;
Error:
Listening on port: 3001
awaiting code to be checked
awaiting oauthResponse.ok
awaiting @me
awaiting userResponse.ok
awaiting user to be found and added
awaiting token to be added
Error occurred: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (node:_http_outgoing:703:11)
at ServerResponse.header (C:xampphtdocsdiscordapiapinode_modulesexpresslibresponse.js:795:10)
at ServerResponse.append (C:xampphtdocsdiscordapiapinode_modulesexpresslibresponse.js:756:15)
at res.cookie (C:xampphtdocsdiscordapiapinode_modulesexpresslibresponse.js:885:8)
at someFunction (C:xampphtdocsdiscordapiapisrcroutesauthindex.js:140:13)
at C:xampphtdocsdiscordapiapisrcroutesauthindex.js:115:16
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
code: 'ERR_HTTP_HEADERS_SENT'
}