所以,在阅读了我的 stackoverflow 帖子、auth0 社区帖子并尝试了多种想法后,我仍然感到困惑。
我有一个nodejsexpress应用程序(和rest api)运行了很多年,但从来没有工作过的一件事(并且我一直在忍受)是,如果用户访问我用中间件保护的url登录后它总是重定向回网站的根目录,而不是请求的网址。
我想说我已经将问题范围缩小到了某个特定区域,但我不确定我已经做到了;
无论如何; 我的 app.js 文件中有所有常用设置:
var strategy = new Auth0Strategy(
{
domain: process.env.AUTH0_DOMAIN,
clientID: process.env.AUTH0_CLIENTID,
clientSecret: process.env.AUTH0_CLIENT_SECRET,
callbackURL: process.env.AUTH0_CALLBACK_URL || 'http://127.0.0.1:3000/callback'
},
function (accessToken, refreshToken, extraParams, profile, done) {
// accessToken is the token to call Auth0 API (not needed in the most cases)
// extraParams.id_token has the JSON Web Token
// profile has all the information from the user
return done(null, profile);
}
);
passport.use(strategy);
// You can use this section to keep a smaller payload
passport.serializeUser(function (user, done) {
done(null, user);
});
passport.deserializeUser(function (user, done) {
done(null, user);
});
// config express-session
var sess = {
secret: 'ThisisMySecret',
cookie: {
httpOnly:false,
secure:false
},
resave: false,
saveUninitialized: false
};
if (app.get('env') === 'prod') {
console.log("prod environment")
app.set('trust proxy', 1); // trust first proxy
sess.cookie.secure = true; // serve secure cookies, requires https
sess.proxy = true;
// console.log("session:sess");
// console.log(sess);
}
app.use(session(sess));
app.use(passport.initialize());
app.use(passport.session());
登录路径:
router.get('/login', function(req, res, next) {
req.session.returnTo = req.query.returnTo; // Store the returnTo value in session
console.log("inside login route: " + req.session.returnTo)
const state = uuidv4();
passport.authenticate('auth0', {
scope: 'openid email profile',
state: state // Pass the returnTo value as the state parameter
})(req, res, next);
});
回调路线:
router.get('/callback', function(req, res, next) {
console.log("inside callback route: " + req.session.returnTo)
passport.authenticate('auth0', function(err, user, info) {
console.log("inside callback authenticate function: " + req.session.returnTo)
console.log(user)
console.log(info)
if (err) { return next(err); }
if (!user) {
console.log(user)
console.log(info)
res.render('beta/failed-login', {
static_path:'/static',
theme:process.env.THEME || 'flatly',
pageTitle : "Access Denied",
pageDescription : "Access Denied",
query:req.query
});
} else {
req.logIn(user, function (err) {
if (err) {console.log(err); return next(err); }
console.log("inside callback route: " + req.session.returnTo)
console.log("user inside callback route: " + user)
const returnTo = req.session.returnTo || '/'; // Retrieve the returnTo value from session
delete req.session.returnTo; // Remove the returnTo value from session
res.redirect(returnTo);
});
}
})(req, res, next);
});
一些中间件:
function secured(req, res, next) {
if (req.isAuthenticated()) {
return next();
}
console.log("query in middleware: " + req.query.state)
console.log("originalUrl in middleware: " + req.originalUrl)
const returnTo = req.query.state || req.originalUrl;
req.session.returnTo = returnTo; // Store the returnTo value in session
console.log("returnTo in middleware: " + returnTo)
console.log("session.returnTo in middleware: " + req.session.returnTo)
res.redirect('/login?returnTo=' + encodeURIComponent(returnTo));
}
以及一个受保护路由示例(很多):
router.get('/user', secured,async function (req, res) {
const { _raw, _json, userProfile } = req.user;
console.log(req.user)
res.render('beta/user', {
userProfile: JSON.stringify(userProfile, null, 2),
static_path:'/static',
theme:process.env.THEME || 'flatly',
pageTitle : "User Profile",
pageDescription : "User Profile",
});
});
当我访问 /user 时,我会在日志中看到以下内容
Server running at http://127.0.0.1:3000/
query in middleware: undefined
originalUrl in middleware: /user
returnTo in middleware: /user
session.returnTo in middleware: /user
inside login route: /user
inside callback route: /user
inside callback authenticate function: /user
false
{ message: 'Unable to verify authorization request state.' }
false
{ message: 'Unable to verify authorization request state.' }
我发现如果我删除
state: state // Pass the returnTo value as the state parameter
从传递到 /login 路由中的 Passport.authenticate 调用的对象中,登录可以工作,但现在它不会重定向..
所以我很困惑,我在本地环境和 Heroku 上托管的生产环境中都遇到了这种行为(不确定这是否相关..)我希望这只是与 https 相关的本地构建问题,但我还没有还没有在本地进行配置,但我的 heroku 版本已设置为 https (https://stockport-badminton.co.uk)
我还注意到,当它在 auth0 日志中失败时,我看到登录成功,但没有成功交换授权码。
有什么想法吗?
也许不是这样的答案,而是意识到我错过了一些明显的东西(或者也许我的解决方案是一个安全漏洞......)
如上所述 - 回调路由没有重定向信息。
所以 - 我只是在全局级别编写了一个新变量并写入该变量..该变量可用于所有路线,现在它可以工作了。