You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TS Express+express-openid-Connect生产环境Cookie不持久化致无限重定向

Firebase Functions + Express + Okta SSO 无限循环问题求助

已被该问题困扰许久,未能找到解决方案,盼求帮助。

背景

  • 基于Firebase Functions的TypeScript Express应用,通过Firebase Hosting配置了自定义域名api.myserver.com,为不同企业提供专属子域名(如https://company.api.myserver.com)。
  • 应客户需求集成Okta SSO,参考Okta官方使用express-openid-connect的示例项目实现。
  • 本地环境通过在Firebase模拟器URL前添加企业前缀(如http://company.api.localhost:5001/project-id/us-central1/function-name)模拟专属域名,SSO功能正常,登录后经/callback可正常跳转至目标页面。

问题

部署到生产环境后,使用真实专属域名https://company.api.myserver.com测试时,虽能正常登录、触发/callback并跳转至目标页面,但加载目标页面时auth(config)会再次重定向至/login,形成无限循环。

经调试发现:

  1. /callback端点能收到Cookie,但未持久化,目标页面加载时req.cookies为空;
  2. 通过req.protocol + "://" + req.get("host") + req.originalUrl打印的请求URL为Firebase默认域名(如https://us-central1-project-id.cloudfunctions.net/login),而非自定义域名,不确定是否与Cookie不持久化相关。

相关代码片段

server.ts

export const app = express();
app.set("trust proxy", true);
app.use(favicon(getAssetUri("favicon.ico")));
app.use(cors()); // 允许跨域请求

const port = 3000;

app.use(express.static("public"));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cookieParser());
app.use(domainConfig()); // 获取主机名
app.use(enterpriseConfig()); // 根据主机名识别企业
app.use(authConfig()); // 下方为该函数代码

app.use(function (req, res, next) {
  res.locals.user = req.oidc?.user;
  const isAuthenticated = req.oidc?.isAuthenticated(); // 始终为false,有时因authConfig()重定向无法执行到此处
  debug(`AA: req.oidc.isAuthenticated() = ${isAuthenticated}`, {
    email: req.oidc?.user?.email,
  });
  next();
});

app.use(genAuthenticateUser);
app.use(genValidateEnterprise);

authConfig()

async function authConfig(
  req: express.Request,
  res: express.Response,
  next: express.NextFunction
): Promise<void> {
  debug("genSSOAuth.CookiesSet", { cookies: req.cookies }); // Cookie始终为空
  const authConfig = getAuthConfig();
  const config = {
    authRequired: false,
    auth0Logout: true,
    baseURL: getBaseURL(req),
    clientID: authConfig.clientID,
    issuerBaseURL: authConfig.issuerBaseURL,
    secret: authConfig.secret,
    errorOnRequiredAuth: true,
    afterCallback: async (
      req: express.Request,
      res: express.Response,
      session: Session,
      decodedState: { [key: string]: any }
    ) => {
      debug("After callback", { // 打印待设置的Cookie,但未持久化
        req,
        res,
        session,
        decodedState,
      });
      return session;
    },
  };

  debug("genSSOAuth.AuthMiddleware.Setup");
  const authMiddleware = auth(config);
  authMiddleware(req, res, next); // 此处再次触发重定向
  debug("genSSOAuth.AuthMiddleware.Setup.Done");
}

内容的提问来源于stack exchange,提问作者Antonio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 11:27:46