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

能否用adal.js/adal-node.js从Azure AD获取SAML2令牌?如何集成Express?

使用ADAL库获取Azure AD SAML2令牌及Express集成方案

一、能不能用ADAL库获取SAML2令牌?

当然可以!不过得区分两个库的适用场景:

  • adal.js:专门给前端浏览器环境用的,主要作用是引导用户完成Azure AD的SAML登录流程,最终获取SAML断言并传递给后端服务。
  • adal-node:针对Node.js服务端场景设计,可通过服务端交互直接获取SAML2令牌(通常以ID令牌或SAML断言形式返回,具体取决于Azure AD应用配置)。

二、具体操作方式

1. 用adal-node在服务端获取SAML2令牌

步骤1:安装依赖

先把需要的包装上:

npm install adal-node express

步骤2:准备Azure AD配置参数

先去Azure AD门户注册你的应用,拿到以下关键参数:

  • tenantId:你的Azure AD租户ID
  • clientId:应用注册生成的客户端ID
  • clientSecret:在应用的「证书和机密」里生成的客户端密钥
  • redirectUri:授权回调地址(必须提前在Azure AD应用的「身份验证」页面添加)
  • samlResourceId:目标SAML服务的实体ID(比如你的应用ID URI,或者第三方SAML服务的实体ID)

步骤3:编写Express集成的核心逻辑

下面是一个可直接运行的示例,包含登录跳转、授权回调、令牌获取的完整流程:

const express = require('express');
const adal = require('adal-node');
const app = express();

// 配置Azure AD参数
const aadConfig = {
  tenantId: '你的租户ID',
  clientId: '你的客户端ID',
  clientSecret: '你的客户端密钥',
  redirectUri: 'http://localhost:3000/auth/callback',
  authorityUrl: `https://login.microsoftonline.com/${aadConfig.tenantId}`,
  samlResource: 'https://你的SAML服务实体ID' // 替换为实际资源ID
};

// 创建ADAL认证上下文
const authContext = new adal.AuthenticationContext(aadConfig.authorityUrl);

// 跳转至Azure AD登录页的路由
app.get('/auth/login', (req, res) => {
  const authUrl = authContext.getAuthorizationUrl({
    clientId: aadConfig.clientId,
    redirectUri: aadConfig.redirectUri,
    responseType: 'code',
    resource: aadConfig.samlResource,
    responseMode: 'form_post' // 若需要纯SAML断言,推荐用form_post模式
  });
  res.redirect(authUrl);
});

// 处理授权回调,交换授权码为令牌
app.get('/auth/callback', (req, res) => {
  const authCode = req.query.code;
  authContext.acquireTokenWithAuthorizationCode(
    authCode,
    aadConfig.redirectUri,
    aadConfig.samlResource,
    aadConfig.clientId,
    aadConfig.clientSecret,
    (err, tokenResponse) => {
      if (err) {
        return res.status(500).send(`令牌获取失败:${err.message}`);
      }
      // tokenResponse中包含idToken(可能是SAML格式)和accessToken
      // 若需要纯SAML断言,可从tokenResponse的idToken字段解析
      res.send(`获取到的SAML相关令牌:<pre>${JSON.stringify(tokenResponse, null, 2)}</pre>`);
    }
  );
});

app.listen(3000, () => {
  console.log('Express服务已启动:http://localhost:3000');
});

2. 用adal.js在前端获取SAML2令牌

如果是前端单页应用场景,可直接用adal.js引导登录并获取令牌:

// 前端页面代码示例
window.aadConfig = {
  tenant: '你的租户ID',
  clientId: '你的客户端ID',
  redirectUri: 'http://localhost:3000/callback',
  postLogoutRedirectUri: 'http://localhost:3000/',
  responseType: 'id_token', // 可获取包含SAML断言的ID令牌
  resource: 'https://你的SAML服务实体ID'
};

const authContext = new AuthenticationContext(window.aadConfig);

// 检查是否已登录,未登录则跳转至Azure AD
if (!authContext.isAuthenticated()) {
  authContext.login();
}

// 在回调页面处理令牌
authContext.handleWindowCallback();
const samlToken = authContext.getCachedToken(window.aadConfig.resource);

三、Express集成常见问题解决

你提到示例能运行但无法集成Express,大概率是以下几个环节出了问题,给你整理了排查和解决方法:

  • 回调地址不匹配:确保Azure AD应用中配置的redirectUri和Express路由的地址完全一致(包括HTTP/HTTPS、端口、路径,比如http://localhost:3000/auth/callback不能少任何部分)。
  • 会话管理缺失:如果需要在Express中保持用户登录状态,建议添加express-session中间件存储令牌,避免每次请求都重新获取:
    const session = require('express-session');
    app.use(session({
      secret: '你的会话密钥',
      resave: false,
      saveUninitialized: true
    }));
    
    // 在回调路由中将令牌存入会话
    authContext.acquireTokenWithAuthorizationCode(..., (err, tokenResponse) => {
      if (!err) {
        req.session.userToken = tokenResponse;
        res.redirect('/dashboard');
      }
    });
    
  • CORS跨域问题:如果前端和后端分离部署,需要在Express中配置CORS中间件允许前端域名的请求:
    const cors = require('cors');
    app.use(cors({ origin: '你的前端域名', credentials: true }));
    
  • SAML断言格式问题:如果需要纯SAML2断言而非JWT格式的ID令牌,可直接调用Azure AD的元数据端点(https://login.microsoftonline.com/{tenantId}/federationmetadata/2007-06/federationmetadata.xml)获取SAML配置,然后构造SAML请求;或者确保adal-node请求的resource参数是目标SAML服务的实体ID,Azure AD会自动返回对应的SAML断言。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:25:20