能否用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租户IDclientId:应用注册生成的客户端IDclientSecret:在应用的「证书和机密」里生成的客户端密钥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
相关产品推荐
相关产品推荐

