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

ExpressJS Passport OIDC回调函数未触发问题求助

问题分析与修复方案

你的Passport OIDC策略回调未触发,核心原因是回调URL配置错误,同时还有几处细节问题导致认证流程不完整,以下是具体修复步骤:

1. 修正回调URL配置

你的oidcConfig中callbackURL设置为http://localhost:3000/home,但实际处理回调的路由是/auth/callback。CILogon会将认证结果发送到你配置的callbackURL,如果地址不匹配,Passport无法捕获回调请求,自然不会触发策略里的回调函数。

修改为:

const oidcConfig = {
  // ...其他配置
  callbackURL: "http://localhost:3000/auth/callback", // 改为回调路由地址
  // ...其他配置
};

2. 清理URL末尾的空格

tokenURL和userInfoURL末尾存在多余空格,会导致HTTP请求地址无效,Passport无法获取令牌和用户信息:

修改为:

const oidcConfig = {
  // ...其他配置
  tokenURL: "https://cilogon.org/oauth2/token", // 去掉末尾空格
  userInfoURL: "https://cilogon.org/oauth2/userinfo", // 去掉末尾空格
};

3. 补充Passport序列化/反序列化函数

Passport需要这两个函数来处理Session中的用户数据存储与恢复,缺失的话就算认证成功,后续请求也无法通过req.user获取用户信息:

添加以下代码:

// 序列化用户到Session
passport.serializeUser((user, done) => {
  done(null, user);
});

// 从Session反序列化用户
passport.deserializeUser((user, done) => {
  done(null, user);
});

4. 调整认证Scope,添加openid

OIDC协议要求必须包含openid Scope,否则无法获取ID Token和用户信息。你当前只设置了profile,需要补充:

修改/auth路由:

app.get("/auth", passport.authenticate("openidconnect", { scope: ["openid", "profile"] }));

修复后的完整代码

const express = require("express");
const app = express();
const cors = require("cors");

// auth
const config = require("./auth/config"); // saved on server only
const session = require("express-session");
const crypto = require("crypto");
const passport = require("passport");
const OIDCStrategy = require("passport-openidconnect").Strategy;

// Body parser to parse incoming and outgoing requests
app.use(express.json());
app.use(cors());

// OIDC auth
const oidcConfig = {
  issuer: "https://cilogon.org",
  clientID: "xx123",
  clientSecret: "XXABC123",
  callbackURL: "http://localhost:3000/auth/callback",
  authorizationURL: "https://cilogon.org/authorize",
  tokenURL: "https://cilogon.org/oauth2/token",
  userInfoURL: "https://cilogon.org/oauth2/userinfo",
};

// Generate a random session secret key
const secretKey = crypto.randomBytes(64).toString("hex");
app.use(
  session({
    secret: secretKey,
    resave: false,
    saveUninitialized: false,
  })
);

app.use(passport.initialize()); // Initialize Passport middleware
app.use(passport.session()); // Enable session support for Passport

// 新增:序列化/反序列化用户
passport.serializeUser((user, done) => {
  done(null, user);
});

passport.deserializeUser((user, done) => {
  done(null, user);
});

passport.use(
  new OIDCStrategy(
    oidcConfig,
    (issuer, sub, profile, accessToken, refreshToken, done) => {
      console.log("profile: ", profile); // 现在应该能正常输出
      console.log("here...");
      return done(null, profile);
    }
  )
);

app.get("/auth", passport.authenticate("openidconnect", { scope: ["openid", "profile"] })); // 修正scope

app.get(
  "/auth/callback",
  passport.authenticate("openidconnect", {
    successRedirect: "/home", // Redirect URL after successful authentication
    failureRedirect: "/login", // Redirect URL after failed authentication
  })
); // Callback URL for handling the OIDC provider's response

app.get("/home", async (req, res) => {
  console.log("home");
  console.log("当前用户:", req.user); // 可以在这里获取用户信息
  const html = `<h1>Welcome to the home page!</h1>`; // Example HTML
  res.send(html);
});

app.get("/profile", (req, res) => {
  // Access the authenticated user's information from 'req.user'
  res.send(`<h1>用户信息</h1><pre>${JSON.stringify(req.user, null, 2)}</pre>`);
});

app.get("/logout", (req, res) => {
  req.logout((err) => {
    if (err) return next(err);
    res.redirect("/");
  });
});

app.listen(3000, () => console.log("server is up and running"));

验证方法

  1. 启动服务后访问http://localhost:3000/auth,完成CILogon登录
  2. 登录成功后控制台会打印profile信息,同时/home路由的req.user能获取到用户数据
  3. 访问http://localhost:3000/profile可以看到完整的用户信息

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 11:37:01