I recently made a react app that utilized the google Oauth2 service. For my server I use nodeJS single sign on with google, on localhost it works perfectly and I'm allowed to store the sessions and log in and out. When I deploy this same nodejs app to heroku I am able to open the google single signon page, click my user account, and return to my app.
BUT, no data is being returned to my application, no user profile is being sent to my app.
const GoogleStrategy = require("passport-google-oauth2").Strategy;
const passport = require("passport");
const GOOGLE_CLIENT_ID = "HIDDEN_KEYmpt.apps.googleusercontent.com";
const GOOGLE_CLIENT_SECRET = "HIDDEN_KEY";
passport.use(
new GoogleStrategy(
{
clientID: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET,
callbackURL: "/auth/google/callback",
proxy: true,
},
function (accessToken, refreshToken, profile, done) {
// usually here it will finish the google authentication process
// and return profile user info, like the google account's email address, etc
// on localhost it returns all that, on heroku it returns nothing
done(null, profile);
}
)
);
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});
I made sure I added my Heroku link to the google Oauth2 list of verified websites, that works fine. I made sure that my data was being received correctly from localhost, as far as the code is concerned, it works perfectly when not deployed to Heroku.
UPDATE: here is the extra NodeJS code for the google auth logic
const CLIENT_URL = "https://mygituhbpageslink/home";
authRouter.get("/login/success", (req, res) => {
// This is where the req.user SHOULD be returned after logging in, but it doesn't find a req.user so it fails
if (req.user) {
res.status(200).json({
success: true,
message: "SUCCESS!",
user: req.user,
});
} else {
res.send(JSON.stringify({
success: false,
message: "REQUEST FAILED!",
user: [],
}));
}
});
authRouter.get("/login/failed", (req, res) => {
res.status(401).json({
success: false,
message: "failure",
user: [],
});
});
authRouter.get("/logout", (req, res) => {
req.logout();
res.redirect(CLIENT_URL);
});
authRouter.get("/google", passport.authenticate("google", { scope: ["email"] }));
authRouter.get(
"/google/callback",
passport.authenticate("google", {
successRedirect: CLIENT_URL,
failureRedirect: "/auth/login/failed",
})
);
module.exports = authRouter;
And also here is the express logic
const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const passport = require('passport');
const session = require('express-session');
const passportSetup = require("./Auth/passport");
const moviesRouter = require('./routes/movies');
const gamesRouter = require('./routes/games');
const booksRouter = require('./routes/books');
const authRouter = require('./routes/auth');
const app = express();
app.use(helmet());
app.use(express.json());
app.use(session({
secret: "secret",
resave: false,
saveUninitialized: true,
proxy: true,
}))
app.use(passport.initialize());
app.use(passport.session());
app.use(cors({
origin: 'https://mygithubpages.github.io',
methods: 'GET, POST, PUT, DELETE',
credentials: true,
}));
// --------------- Routes --------------- //
app.use("/auth", authRouter);
// other routes
module.exports = app;
CodePudding user response:
Try to update this since your cookies is cross-site if you host it on Heroku, the cookie is set to your browser when you get the callback from google Oauth2.0, you need to be able to get this cookie on your request header when you re going to do the request on the frontend to authenticate :
const app = express();
app.use(helmet());
app.use(express.json());
// is better to put the cors setting on the top
app.use(cors({
origin: 'https://mygithubpages.github.io',
methods: 'GET, POST, PUT, DELETE',
credentials: true,
}));
app.set('trust proxy', 1) // you need to add this
app.use(session({
secret: "secret",
resave: false,
saveUninitialized: false,
proxy: true, // this is optional it depend which server you host, i am not sure about Heroku if you need it or not
cookie: {
secure: "auto", // this will set to false on developement, but true on Heroku since is https so this setting is required
maxAge: 10000 // 10 sec for testing
sameSite: "none", //by default in developement this is false if you're in developement mode
},
}))
Beware express-session is storing session on the backend / database, and if you don't defined where to store it in cookie's property, express-session will store it by default in MemoryStore, and this is purposely not designed for a production environment. is meant only for debugging and developing, you will need to use a compatible session store. You can check on the express session documentation : https://github.com/expressjs/session