I'm learning about authentication and JWT by building a small project. But I'm stuck trying to send the JWT (JSON Web Token) back to the frontend after a user logs in with Google OAuth. The problem is, when the backend redirects after login, it loses the headers containing the JWT.
Here's what I'm using: React with Vite for the frontend, and Node.js with Express.js for the backend. For Google authentication, I'm using a strategy called passport-google-oauth20 from Passport.js, with some tweaks.
Here's a snippet of my backend code for the Google authentication strategy and routes:
// Backend Code Snippet
passport.use(new GoogleStrategy(
{
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: process.env.FRONTEND_URL + "/auth/google/callback",
},
async (accessToken, refreshToken, profile, cb) => {
try {
// Logic to create or find user
// ...
return cb(null, user);
} catch (error) {
return cb(error);
}
}
));
router.get("/google", passport.authenticate("google", { scope: ["profile"] }));
router.get(
"/google/callback",
passport.authenticate("google", {
session: false,
failureRedirect: process.env.FRONTEND_URL + "/auth/login",
}),
authController.google_callback
);
And here's how I generate the JWT and set the headers in the google_callback function:
// Google Callback Implementation
exports.google_callback = asyncHandler(async (req, res, next) => {
let user = req.user;
!user && res.redirect(frontend_url + "/auth/login");
const opts = {};
opts.expiresIn = 3600; // 1 hour
const token = jwt.sign({ user }, secret, opts);
res.setHeader("authorization", `Bearer ${token}`);
res.setHeader("Access-Control-Expose-Headers", "authorization");
// res.redirect(frontend_url + "/");
res.status(200).json({
status: "success",
token: token,
});
});
Despite my efforts, I haven't found a way to send the JWT back to the frontend without losing it. The only way I've been able to access the Google auth is by redirecting from the frontend, like this:
// Frontend Code Snippet
<a href={import.meta.env.VITE_BACKEND_URL + "/auth/google"}>
Continue with Google
</a>
And using Axios for the GET request results in a CORS problem:
Access to XMLHttpRequest at 'backend_url/auth/google' from origin 'frontend' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
If anyone has experience with integrating Google OAuth with JWT authentication, I'd really appreciate some guidance. Thanks in advance for any help.
I anticipated sending the JWT in the headers of the response along with the redirection, intending to then store it in local storage on my frontend. However, when I used res.redirect, the token was lost. Alternatively, when employing res.json, I faced the dilemma of being unable to redirect and store the token in my frontend.