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

Access Token未过期时,如何用MSAL.js刷新Identity Token?

Outlook桌面端NAA环境下MSAL.js Identity Token刷新问题解决方案

问题背景

在Outlook桌面客户端的NAA(Nested App Authentication)环境中使用MSAL.js处理Azure AD认证时,出现Identity Token早于Access Token过期,但调用acquireTokenSilent并传入forceRefresh: true仍无法获取新Identity Token的问题,该功能在浏览器端正常。


1. 为何forceRefresh: true无法刷新Identity Token?

MSAL.js的acquireTokenSilent核心逻辑以维护Access Token有效性为优先:

  • 当设置forceRefresh: true时,默认触发的是Access Token的刷新流程,Identity Token仅作为附属产物返回,而非独立刷新目标。
  • Outlook桌面的NAA嵌入式环境存在特殊缓存隔离机制,即使强制刷新,若当前Access Token未过期,Azure AD可能不会返回新的Identity Token,而是复用缓存中的旧令牌。
  • MSAL.js的缓存判断逻辑中,ID Token的刷新依赖Access Token状态,而非自身过期时间,导致ID Token过期后无法被主动触发刷新。

2. 是否可以独立于Access Token刷新Identity Token?

可以,需绕过acquireTokenSilent的默认逻辑,直接通过Refresh Token发起请求:

  • Identity Token属于OpenID Connect范畴,只要持有有效的Refresh Token,请求openid、profile等基础OIDC scope,即可独立获取新的Identity Token,无需依赖Access Token状态。
  • 注意:需确保Refresh Token未过期,且应用拥有获取ID Token的权限。

3. 已知问题与解决方法

解决方法1:使用acquireTokenByRefreshToken主动刷新ID Token

直接调用MSAL.js的acquireTokenByRefreshToken方法,指定OIDC scope强制获取新的Identity Token:

// 获取当前活跃账户
const activeAccount = msalInstance.getActiveAccount();
if (!activeAccount) {
    console.error("No active account found");
    return;
}

// 从缓存中获取Refresh Token
const refreshTokenEntry = msalInstance.getTokenCache().getRefreshTokensByAccount(activeAccount)[0];
if (!refreshTokenEntry) {
    console.error("No refresh token available in cache");
    return;
}

const refreshRequest = {
    scopes: ["openid", "profile"],
    refreshToken: refreshTokenEntry.secret
};

msalInstance.acquireTokenByRefreshToken(refreshRequest)
    .then(response => {
        console.log("Successfully refreshed Identity Token: ", response.idToken);
    })
    .catch(error => {
        console.error("Failed to refresh Identity Token: ", error);
        // 若Refresh Token过期,需触发交互式认证(如acquireTokenPopup)
    });

解决方法2:精准清除ID Token缓存条目

不清除全部缓存,仅删除已过期的ID Token后再调用acquireTokenSilent:

const activeAccount = msalInstance.getActiveAccount();
if (activeAccount) {
    // 获取缓存中的ID Token条目并检查过期状态
    const idTokenEntries = msalInstance.getTokenCache().getIdTokensByAccount(activeAccount);
    idTokenEntries.forEach(entry => {
        const decodedToken = jwt_decode(entry.secret);
        const isExpired = Date.now() >= decodedToken.exp * 1000;
        if (isExpired) {
            msalInstance.getTokenCache().removeIdToken(entry);
        }
    });

    // 重新调用acquireTokenSilent
    msalInstance.acquireTokenSilent({
        scopes: ["openid", "profile"],
        forceRefresh: true
    })
    .then(response => {
        console.log("Refreshed Identity Token after clearing expired cache: ", response.idToken);
    })
    .catch(error => console.error(error));
}

解决方法3:升级MSAL.js版本

部分旧版本MSAL.js在嵌入式WebView环境中存在ID Token刷新逻辑bug,升级至最新稳定版(如v2.x或v3.x)可修复部分兼容性问题。

已知问题

  • MSAL.js在嵌入式环境(如Outlook桌面WebView)中的缓存策略与浏览器端存在差异,部分缓存操作行为不一致,需针对性调整。
  • Azure AD在Refresh Token请求中,若未明确指定openid scope,可能仅返回Access Token,因此必须包含该scope。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 17:52:45