React集成Azure AD:刷新令牌机制及会话过期重定向登录求助
React集成Azure AD:Refresh Token机制与会话过期自动重定向实现
Azure AD Refresh Token 工作机制
- 用户首次通过Azure AD登录后,若请求了
offline_access权限,服务端会返回Access Token和Refresh Token - Access Token有效期较短(默认1小时),用于调用受保护的API;Refresh Token有效期更长(由Azure AD策略决定,最长90天),专门用于在Access Token过期时获取新的Access Token
- 当Access Token过期,应用可通过MSAL库自动调用Azure AD的令牌端点,用Refresh Token换取新的Access Token,同时可能返回新的Refresh Token(滚动刷新,延长有效期)
- 若Refresh Token失效(如用户密码变更、账号禁用、超过有效期),则无法继续静默获取令牌,必须引导用户重新登录
React中实现会话过期自动重定向
以下基于官方推荐的@azure/msal-react和@azure/msal-browser库实现:
1. 初始化MSAL实例
import { PublicClientApplication } from '@azure/msal-browser'; const msalConfig = { auth: { clientId: '你的Azure AD应用Client ID', authority: 'https://login.microsoftonline.com/你的租户ID', redirectUri: '应用回调地址(需在Azure AD后台配置)' } }; export const msalInstance = new PublicClientApplication(msalConfig);
2. 监听令牌获取失败事件
通过MSAL的事件回调捕获令牌失效场景,自动触发登录重定向:
import { EventType } from '@azure/msal-browser'; msalInstance.addEventCallback((event) => { if (event.eventType === EventType.ACQUIRE_TOKEN_FAILURE) { // 判断是否为refresh token失效或令牌过期导致的失败 const isTokenInvalid = event.error.errorMessage.includes('invalid_grant') || event.error.errorMessage.includes('token_expired'); if (isTokenInvalid) { msalInstance.loginRedirect(); } } });
3. 路由守卫验证令牌状态
在受保护路由跳转前检查令牌有效性,失效则重定向登录:
import { useMsal } from '@azure/msal-react'; import { Navigate } from 'react-router-dom'; export const ProtectedRoute = ({ children }) => { const { instance, accounts } = useMsal(); const activeAccount = accounts[0]; // 无活跃账号直接跳转登录 if (!activeAccount) { return <Navigate to="/" replace />; } // 检查令牌是否过期 const tokenClaims = instance.getActiveAccount()?.idTokenClaims; const isTokenExpired = tokenClaims?.exp * 1000 < Date.now(); if (isTokenExpired) { // 尝试静默刷新令牌,失败则重定向登录 instance.acquireTokenSilent({ account: activeAccount, scopes: ['openid', 'profile', 'offline_access'] // 必须包含offline_access才能获取refresh token }).catch(() => { instance.loginRedirect(); }); } return children; };
4. 定时检查令牌有效期
设置定时器提前检测令牌状态,避免用户操作时突然过期:
import { useEffect } from 'react'; import { useMsal } from '@azure/msal-react'; export const TokenExpiryChecker = () => { const { instance, accounts } = useMsal(); useEffect(() => { const checkExpiry = () => { const activeAccount = accounts[0]; if (!activeAccount) return; const tokenClaims = instance.getAccountByUsername(activeAccount.username)?.idTokenClaims; if (!tokenClaims) return; // 提前5分钟触发检查,预留刷新时间 const warnTime = tokenClaims.exp * 1000 - 5 * 60 * 1000; if (Date.now() >= warnTime) { instance.acquireTokenSilent({ account: activeAccount, scopes: ['openid', 'profile', 'offline_access'] }).catch(() => { instance.loginRedirect(); }); } }; // 每分钟执行一次检查 const interval = setInterval(checkExpiry, 60 * 1000); return () => clearInterval(interval); }, [instance, accounts]); return null; };
注意事项
- 必须在Azure AD应用注册后台配置正确的
redirectUri,并确保应用已获得offline_access权限 - 不要手动存储或操作Refresh Token,MSAL库会自动管理令牌缓存
- 静默刷新失败时,务必触发重定向登录,此时Refresh Token已无法使用
内容的提问来源于stack exchange,提问作者Oded Kessler
相关产品推荐
相关产品推荐

