node.js - Kubernetes 中的路由之间没有恢复 NodeJS Express 会话
问题描述
我们有一个启用并启用的 NodeJSexpress
服务器。我们已经连接了会话数据库,并且可以验证是否正在创建会话。我们的应用程序将没有令牌 cookie 的用户重定向到 Auth0 进行身份验证,然后他们将被重定向回我们的应用程序。它确实成功地设置了允许我们的用户登录的 ID 令牌。但是,passport auth0 策略抱怨它无法验证身份验证状态。express-session
express-mysql-session
/callback
'Unable to verify authorization request state.'
服务器代码如下,其他部分注释掉了。连接到会话数据库是成功的,因为我们可以看到每个请求都创建了会话。
const options = {
database: process.env.SESSION_DB_NAME || "sessions",
host: process.env.SESSION_DB_HOST! as string,
password: process.env.SESSION_DB_PASSWORD! as string,
port: parseInt(process.env.SESSION_DB_PASSWORD || "3306", 10),
user: process.env.SESSION_DB_USER! as string,
};
const sessionStore = new MySQLStore(options);
app.use(
session({
cookie: {
httpOnly: true,
maxAge: 24 * 3600 * 1000, // 1 day
secure: true,
},
resave: false,
saveUninitialized: true,
secret: process.env.SESSION_SECRET!,
store: sessionStore,
})
);
app.get("/login", (request, response, next) => {
// if there is no session, it's a server error
if (!request.session) {
console.error(new Error("No session in /login"));
return response.status(500).send("Server error: No Session");
}
return passport.authenticate("auth0", {
scope: "openid email profile",
})(request, response, next);
});
console.log("router: Auth0 Callback");
app.get("/callback", (request, response, next) => {
const domain = request.hostname;
console.log(request.session);
passport.authenticate("auth0", (auth0Error, token, info) => {
// if there was a problem authenticating
if (auth0Error) {
console.error(auth0Error);
return response.status(500).send();
}
// ensure we have a session. The middleware should be giving us one.
if (!request.session) {
console.error("No session in /callback.");
return response.status(500).send();
}
// if we couldn't log in
if (!token) {
if (info) {
console.log(info);
return response.status(500).send(info.message);
}
// redirect to the login page
return response.status(401).send("Cannot log you in.");
}
// parse the token we get
const user = jwt.decode(token);
// if there is no valid user token, we've got bigger problems
if (!user) {
console.error("Token is falsey after authenticating.");
return response.status(500).send();
} else if (typeof user === "string") {
console.error("Cannot decode JWT after authenticating");
return response.status(500).send();
}
request.logIn(user, (logInError) => {
// redirect to desired route
// ...
});
})(request, response, next);
});
router.get("/*", (request, response, next) => {
passport.authenticate("jwt", (authenticationError, isAuthenticated, info) => {
// Log in successful via existing JWT
if (isAuthenticated) {
return next();
}
// handle unauthenticated situations
// ...
})(request, response, next);
});
我在https://github.com/auth0/passport-auth0/issues/70尝试了以下建议:
- app.set("信任代理", 1")
- 会话 cookie 已设置为安全
- 仅在 https 上提供服务
- 使用 mysql 会话存储和默认内存存储
我们在 kubernetes 集群中运行服务器,使用 ClusterIP 作为入口。环境变量设置正确,我很确定。当我在本地运行它时,我没有任何问题。
什么可能导致会话无法恢复,而是随着每个请求重新创建?
解决方案
您的问题是一年多前发布的,所以我认为您已经修复了它,但我想我会发布我的解决方案来帮助其他人。我最近遇到了同样的问题,尽管我使用的是 Apache 反向代理而不是 Kubernetes 集群。
我在另一个 SO 问题中发布了我的解决方案:https ://stackoverflow.com/a/67891167/8221175
简而言之,我的 Apache 配置缺少这些行:
RequestHeader set X-Forwarded-Proto expr=%{REQUEST_SCHEME}
RequestHeader set X-Forwarded-SSL expr=%{HTTPS}
ProxyPass / http://localhost:8001/
ProxyPassReverse / http://localhost:8001/
这与 express 的其他会话/cookie 配置(请参阅 SO 链接)一起修复了它。我的会话现在仍然存在,我不再有这个问题。
对于那些对为什么“无法验证授权请求状态”感兴趣的人。消息已发出,请在此 GitHub 问题中查看我的答案:https ://github.com/auth0/passport-auth0/issues/89#issuecomment-856971807
推荐阅读
- java - 如何在不使用任何布局的情况下使文本居中?
- javascript - “prop `value` 的值无效”的错误是什么
- python - Fastest Way to Find the Dot Product of a Large Matrix of Vectors
- java - Spring Zuul - 抛出连接被拒绝
- typescript - 如何解决 passport-http-bearer TypeScript 重载类型问题?
- r - 如何计算 7 日均线?另一种方法
- html - 占位符和光标定位 CSS
- python - 动态更改 Python 'Requests' 标头以迭代 API URL 端点的问题
- laravel - Laravel 上的 Facade\Ignition\Exceptions\ViewException 错误?
- c - 为什么我的 Super Reduced String(HackerRank) 问题的解决方案在我的计算机上运行良好,但在 HackerRank 中给出错误答案?