如何使用Azure AD Access Token实现React SPA与Node.js后端REST API的授权验证及角色访问控制?
验证Azure AD Access Token & 基于角色授权的完整方案
看起来你已经搞定了前端React的Azure AD Implicit Flow登录,接下来后端Node.js的Token验证和角色授权其实没那么复杂,我给你梳理一套落地性强的方案:
一、先明确安全访问的正确流程
先把前后端的交互逻辑理清楚,这是后续所有验证的基础:
- 前端React通过Implicit Flow拿到Azure AD的Access Token(你已经实现这一步了)
- 前端每次调用后端API时,把Token放在请求头的
Authorization里,格式是Bearer <你的Access Token> - 后端收到请求后,先验证Token的有效性,再检查用户角色是否匹配端点的权限要求
- 验证通过就返回数据,不通过就返回401(未授权)或403(无权限)
二、后端验证Azure Access Token的有效性
Node.js这边推荐用微软官方的azure-ad-jwt库来做Token验证,轻量且靠谱,步骤如下:
1. 安装依赖
npm install azure-ad-jwt --save
2. 编写Token验证中间件
创建一个authMiddleware.js文件,统一处理所有请求的Token验证:
const azureAdJwt = require('azure-ad-jwt'); const validateToken = async (req, res, next) => { // 从请求头提取Token const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).json({ message: '请提供有效的访问令牌' }); } const token = authHeader.split(' ')[1]; const validationOptions = { audience: '<你的API应用的Application ID URI>', // 必须和Azure AD里配置的API标识符一致,比如api://xxx-xxx-xxx issuer: 'https://sts.windows.net/{你的Azure AD租户ID}/' // 替换成你的租户ID }; try { // 验证Token的签名、过期时间、受众等核心信息 const decodedToken = await azureAdJwt.verify(token, validationOptions); // 把解析后的用户信息挂载到req上,方便后续授权使用 req.user = decodedToken; next(); // 验证通过,继续执行后续路由逻辑 } catch (err) { console.error('Token验证失败:', err); return res.status(401).json({ message: '令牌无效或已过期' }); } }; module.exports = validateToken;
划重点:
audience必须严格匹配你在Azure AD中注册的后端API的Application ID URI,如果和Token里的aud字段不一致,验证直接失败。
三、基于角色的权限控制
Azure AD的Access Token里会包含你给用户分配的角色(前提是你已经在Azure AD里配置了角色并分配给用户),通常存在Token的roles数组里。接下来做角色授权:
1. 编写角色授权中间件
在authMiddleware.js里新增角色校验的逻辑:
// 新增的角色授权中间件,接收需要的角色作为参数 const requireRole = (requiredRole) => { return (req, res, next) => { const userRoles = req.user.roles || []; if (!userRoles.includes(requiredRole)) { return res.status(403).json({ message: '你没有访问该接口的权限' }); } next(); }; }; // 现在导出两个中间件 module.exports = { validateToken, requireRole };
2. 在API路由中使用中间件
比如你的Express路由文件:
const express = require('express'); const { validateToken, requireRole } = require('./authMiddleware'); const router = express.Router(); // 普通用户和管理员都能访问的产品列表接口 router.get('/products', validateToken, (req, res) => { res.json({ products: [{ id: 1, name: '测试产品' }] }); }); // 只有Admin角色能访问的订单列表接口 router.get('/orders', validateToken, requireRole('Admin'), (req, res) => { res.json({ orders: [{ id: 1, orderNo: 'ORD-2024-001' }] }); }); // 只有Admin能更新产品详情 router.put('/products/:id', validateToken, requireRole('Admin'), (req, res) => { const productId = req.params.id; // 这里写你的更新逻辑 res.json({ message: `产品${productId}更新成功` }); }); module.exports = router;
四、几个关键注意事项
- 角色配置:你得先在Azure AD的后端API应用注册里,手动添加
Admin和Normal User这两个角色,然后给用户或组分配对应的角色,这样生成的Token里才会有roles字段。 - HTTPS必须用:生产环境一定要用HTTPS传输Token,不然Token很容易被劫持,安全性全无。
- Token过期处理:前端要监听Token的
exp字段(过期时间),快过期时用Azure AD的静默刷新机制获取新Token,别让用户频繁登录。 - 最小权限原则:给用户分配角色时,尽量只给必要的权限,比如普通用户只需要访问产品列表,就别给Admin角色。
内容的提问来源于stack exchange,提问作者akhil
相关产品推荐
相关产品推荐

