如何作废微软Active Directory认证下发的未过期access_token
实现Azure AD禁用用户后立即作废未过期Access Token的方案
Azure AD本身签发的access_token是自包含的JWT令牌,默认情况下在过期时间前都会被认为有效,Azure AD不会主动回收已签发的未过期access_token,所以需要在API侧额外增加校验逻辑实现立即作废的需求。
核心思路
在原有JWT基础校验逻辑的基础上,增加对用户账号状态的实时校验,可搭配缓存/令牌吊销列表机制降低性能损耗。
具体实现步骤
扩展passport-azure-ad的校验逻辑
原有passport-azure-ad的校验只会验证JWT的签名、签发方、受众、过期时间等基础字段,你需要在自定义的verify回调中增加用户状态查询逻辑:- 从解码后的JWT中提取用户唯一标识
oid(对象ID)字段 - 调用Microsoft Graph API的
GET /users/{oid}接口,查询对应用户的accountEnabled属性值 - 如果返回的
accountEnabled为false,直接返回校验失败,拒绝API访问
参考代码:
const passport = require('passport'); const { BearerStrategy: AzureADBearerStrategy } = require('passport-azure-ad'); const { ConfidentialClientApplication } = require('@azure/msal-node'); // 初始化MSAL客户端用于调用Graph API const msalClient = new ConfidentialClientApplication({ auth: { clientId: "你的应用客户端ID", clientSecret: "你的应用客户端密钥", authority: "https://login.microsoftonline.com/你的租户ID" } }); passport.use(new AzureADBearerStrategy({ identityMetadata: "https://login.microsoftonline.com/你的租户ID/v2.0/.well-known/openid-configuration", clientID: "你的应用客户端ID" }, async (token, done) => { try { // 提取用户oid const userId = token.oid; // 获取Graph API调用凭证 const graphTokenRes = await msalClient.acquireTokenByClientCredential({ scopes: ["https://graph.microsoft.com/.default"] }); // 查询用户状态 const userRes = await fetch(`https://graph.microsoft.com/v1.0/users/${userId}?$select=accountEnabled`, { headers: { Authorization: `Bearer ${graphTokenRes.accessToken}` } }); const userInfo = await userRes.json(); // 用户已禁用直接返回校验失败 if (!userInfo.accountEnabled) { return done(null, false, { message: "账号已被禁用" }); } // 原有业务校验逻辑 return done(null, token); } catch (err) { return done(err); } }));- 从解码后的JWT中提取用户唯一标识
增加缓存降低性能损耗
每次API请求都调用Graph API会增加响应延迟,可增加本地/分布式缓存存储用户的禁用状态:- 缓存key为用户
oid,缓存值为用户是否禁用的状态,缓存过期时间可设置为1~5分钟,可根据业务对作废延迟的容忍度调整 - 如果业务对立即作废的要求不高,也可以直接将Azure AD中access_token的有效期设置为更短的时间(最短支持10分钟),无需额外加校验逻辑。
- 缓存key为用户
可选优化:主动吊销用户会话
如果你同时管控客户端的认证逻辑,可以在用户禁用后主动调用Microsoft Graph的revokeSignInSessions接口,该接口会立即使该用户的所有刷新令牌失效,用户无法再获取新的access_token,搭配前面的校验逻辑可以实现全链路的权限回收。
注意事项
不要依赖令牌的nbf和exp字段做唯一校验,这两个字段只能证明令牌本身的有效期,无法反应账号的实时状态。
内容的提问来源于stack exchange,提问作者Hassan
相关产品推荐
相关产品推荐

