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"));
验证方法
- 启动服务后访问
http://localhost:3000/auth,完成CILogon登录 - 登录成功后控制台会打印
profile信息,同时/home路由的req.user能获取到用户数据 - 访问
http://localhost:3000/profile可以看到完整的用户信息
内容的提问来源于stack exchange,提问作者bluebac
相关产品推荐
相关产品推荐

