我遇到了一个非常令人沮丧的错误。在本地开发环境中,当我使用passport身份验证进行谷歌OAuth请求时,它能够完美工作。但是将其推送到Heroku上时,返回状态码200而不是在开发环境中得到的状态码302,这会让我重定向到谷歌OAuth登录页面。屏幕只是显示空白,没有任何错误信息。我尝试故意使用错误的客户端ID来发起请求,但它甚至都没有注册这个请求。
登录
在Heroku上,这个链接会带我进入一个空白页面,而且根本没有注册任何请求。
请帮忙解决!
服务器端护照:
客户端(Client) - 端
// .use is generic register
passport.use(
new GoogleStrategy(
{
clientID: keys.googleClientID,
clientSecret: keys.googleClientSecret,
// need url for where user should go on callback after they grant permission to our application on google auth page
callbackURL: "/auth/google/callback",
// have to authorize this callback url in the google oauth console.developors screen because of security reasons
proxy: true // trust the proxy our request runs through so heroku callbacks to the correct url
},
async (accessToken, refreshToken, profile, done) => {
// after authenticated on the next get request to google it will call this with the accessToken, aka callback function
// console.log("access token", accessToken);
// console.log("refresh token", refreshToken);
// console.log("profile", profile);
// check to see if user id already exists before saving it to DB so it does not overlap...mongoose query...asynchronous operation
// using async await
const existingUser = await User.findOne({
googleId: profile.id
});
// get promise response
if (existingUser) {
// already have record
// finish passport auth function
return done(null, existingUser); // passes to serialize user so serialize can pull that user id
}
// we don't have a new record so make one
const user = await new User({
// creates new model instance of user
googleId: profile.id
}).save(); // have to save it to DB
// get promise from save since asynchronize, then finish with response
done(null, user); // passes to serialize user so serialize can get that id
}
)
); // create new instance of GoogleStrategy
服务器端API:
app.get(
"/auth/google", // passport, attempt to authenticate the user coming in on this route
passport.authenticate("google", {
// google strategy has internal code, that is 'google', so passport will know to find the google passport authenticator
scope: ["profile", "email"] // options object
// specifies to google we want access to this users profile and email information from their account, these are premade strings in the google oauth process not made up
})
);
// in this callback route they are going to have the code, and google will see that and it will handle it differnetly by exchanging the code for an actual profile, it will call the next part of the GoogleStrategy, aka the accessToken to be saved to Database
// @route GET auth/google/callback
// @desc Get callback data from google to redirect user if signed in
// @access Private can only access this after signed in
app.get(
"/auth/google/callback",
passport.authenticate("google"),
// after authenticate process is done, send user to correct route
(req, res) => {
// redirect to dashboard route after sign-in
res.redirect("/surveys");
// full HTTP requrest, so it reloads versus AJAX request which uses react and redux and is much faster
}
);
客户端(Client) - 端
<div
className="collapse navbar-collapse nav-positioning"
id="navbarNav"
>
<ul className="navbar-nav">
<li className="nav-item google-link">
<a className="nav-link" href="/auth/google">
Google Login
</a>
</li>
</ul>
</div>
Index.js
// Route file, or starter file
const express = require("express");
// node.js does not have support from E6,
// so we use common js modules
// import vs require :
// common vs ES6
// bring in mongoose
const mongoose = require("mongoose");
// tell express it must make use of cookies when using passport
const cookieSession = require("cookie-session");
const passport = require("passport");
// pull in body-parser middleware to get req.body
const bodyParser = require("body-parser");
// connect it to DB in keys so it is not posted to github
const keys = require("./config/keys");
//connect mongoose
mongoose.connect(keys.mongoURI);
// ########## MODELS ################
// THIS MUST BE ABOVE WHERE YOU USE IT, SO ABOVE PASSPORT
require("./models/User");
require("./models/Survey");
// don't have to require recipient because its included inside Survey
// pull in passport service, we are not returning anything in passport, so we do not need const passport because nothing to assign
require("./services/passport");
// Generate a new application that represents a running express app
const app = express(); // vast majority use single app
// this will listen for incoming requests, and route them on to different route handlers
// parser so every time a req has a req.body comes in then it will be assigned to the req.body property
app.use(bodyParser.json());
app.use(
cookieSession({
// age for auth cookies to last... 30 days
maxAge: 30 * 24 * 60 * 60 * 1000,
// give cookie a key
keys: [keys.cookieKey]
})
);
// tell passport to use cookies
app.use(passport.initialize());
app.use(passport.session());
// done with authentication flow
//require that file returns a function, which is then immediately called with the app object
require("./routes/authRoutes")(app);
require("./routes/billingRoutes")(app);
require("./routes/surveyRoutes")(app);
if (process.env.NODE_ENV === "production") {
// if in production make sure express will serve up production assets
// like main.js
app.use(express.static("client/build"));
// Express will serve up index.html file if it doesn't recognize the routes
const path = require("path");
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
});
}
// dynamically figure out what port to listen to... Heroku, heroku will inject env variables in moment of deploy, but only works in production not development environment
const PORT = process.env.PORT || 5000; // if heroku port exists assign it that, else, assign it 5000
app.listen(PORT); // listen for requests and route them to the correct handler on port 5000
/* ###### HEROKU PREDEPLOY ##### */
// specifiy node version and start script for heroku in package.json
// make .gitignore for dependencies which should not be committed on deploy, heroku will install them itself
// app.use wires up middleware for our application
// ############### TIPS
/*
Google first, because its been asked before...
Run in module
*/
/auth/google
的客户端代码以及服务器端API呢? - yaswanth