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

如何在NextJS中实现SAML SSO认证?无需依赖Express后端

问题描述

我目前有一个带SSO认证的门户页面,用户点击‘Sign in’按钮后,应用会自动跳转至SSO登录页。该功能基于React前端与Express后端实现,运行正常。

后端认证代码借助passport和passport-saml库实现,示例如下:

// initialize SAML auth
var samlStrategy = new saml.Strategy(
  {
    callbackUrl: process.env.CALLBACK_URL,
    entryPoint: process.env.ENTRY_POINT,
    issuer: process.env.ISSUER,
    cert: process.env.CERTIFICATE
  },
  function (profile, done) {
    return done(null, profile);
  }
)

//the middleware
app.use(passport.initialize()); // init passport on every route call.
app.use(passport.session()); // allow passport to use "express-session".

// passport lifecycle
passport.use(samlStrategy);
passport.serializeUser(function(user, done) {
  done(null, user);
});
passport.deserializeUser(function(user, done) {
  done(null, user);
});

其中CALLBACK_URL示例为:https://login.microsoftonline.com/xxx/saml2,entryPoint为AWS Cognito链接:urn:amazon:cognito:sp:{zone_string}_{code}。

现在我希望将应用迁移至NextJS,由NextJS独立处理认证流程,不再依赖Express服务器。请问是否可行?能否在NextJS中集成passport?我曾尝试但失败了。


解决方案

完全可行,Next.js可以通过API Routes集成Passport及passport-saml,替代原Express后端的认证逻辑。以下是具体实现步骤:

1. 安装依赖

首先安装所需包:

npm install passport passport-saml express-session next-session

2. 创建Passport配置文件

在项目根目录创建lib/passport.js,配置SAML策略:

import passport from 'passport';
import { Strategy as SamlStrategy } from 'passport-saml';

passport.use(new SamlStrategy(
  {
    callbackUrl: process.env.CALLBACK_URL,
    entryPoint: process.env.ENTRY_POINT,
    issuer: process.env.ISSUER,
    cert: process.env.CERTIFICATE,
  },
  (profile, done) => {
    // 可根据需求扩展用户信息处理逻辑,比如存入数据库
    return done(null, profile);
  }
));

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

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

export default passport;

3. 创建认证相关API Routes

3.1 登录跳转API (pages/api/auth/sso/login.js)

import passport from '../../../lib/passport';
import nextSession from 'next-session';

const getSession = nextSession({
  store: null, // 生产环境建议用Redis等持久化存储,避免内存泄漏
  secret: process.env.SESSION_SECRET,
  cookie: {
    secure: process.env.NODE_ENV === 'production',
    httpOnly: true,
  },
});

export default async function handler(req, res) {
  await getSession(req, res);
  passport.initialize()(req, res, () => {
    passport.authenticate('saml')(req, res);
  });
}

3.2 SAML回调API (pages/api/auth/sso/callback.js)

import passport from '../../../lib/passport';
import nextSession from 'next-session';

const getSession = nextSession({
  store: null,
  secret: process.env.SESSION_SECRET,
  cookie: {
    secure: process.env.NODE_ENV === 'production',
    httpOnly: true,
  },
});

export default async function handler(req, res) {
  await getSession(req, res);
  passport.initialize()(req, res, () => {
    passport.session()(req, res, () => {
      passport.authenticate('saml', {
        successRedirect: '/dashboard', // 登录成功后跳转页面
        failureRedirect: '/login', // 登录失败跳转页面
      })(req, res);
    });
  });
}

4. 前端登录按钮实现

在页面中添加登录按钮,点击后触发SSO跳转:

// 示例页面组件
export default function Home() {
  return (
    <div>
      <h1>SSO Portal</h1>
      <a href="/api/auth/sso/login">Sign in</a>
    </div>
  );
}

5. 关键注意事项

  • Session存储:开发环境可临时用内存存储,生产环境必须使用Redis等持久化存储(如connect-redis),避免Next.js服务器重启后会话丢失。
  • 环境变量:确保CALLBACK_URL、ENTRY_POINT、ISSUER、CERTIFICATE、SESSION_SECRET等变量在.env.local中正确配置。
  • HTTPS要求:生产环境必须启用HTTPS,否则Session Cookie的secure属性无法生效,同时需保证SAML服务商的回调地址与Next.js部署地址完全一致。
  • 会话中间件:Next.js API Routes默认不保留会话,必须通过next-session或类似工具处理会话逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 09:46:27