MSAL.js 和 Axios - aquireTokenPopup 交互正在进行中

问题描述 投票:0回答:1

我们使用 axios 请求拦截器从 MSAL.js 获取访问令牌,并将其作为不记名令牌添加到我们后端的所有 API 请求中:

async acquireToken() {
  const accounts = msalInstance.getAllAccounts();

  if (accounts.length === 0) return null;

  const request = {
    scopes: process.env.scopes || [],
    account: accounts[0],
  };

  try {
    return await msalInstance.acquireTokenSilent(request);
  } catch (error) {
    if (error instanceof InteractionRequiredAuthError) {
      return await msalInstance.acquireTokenPopup(request);
    }

    return null;
  }
}

async getAccessToken() {
  const token = await acquireToken();
  return token?.accessToken || '';
}

axiosInstance.interceptors.request.use(
  async (config) => {
    const configured = config;
    const token = await getAccessToken();
    configured.headers.Authorization = `Bearer ${token}`;
    return configured;
  },
  (error: any) => Promise.reject(error)
);

当用户在应用程序内打开某个路由时,会同时发送多个请求,如下所示:

useEffect(() => {
  Promise.all([getMovies(), getActors()]).then(([_movies, _actors]) => {
    // ...
  });
}, []);

我们真的不想按顺序进行调用,因为其中一些调用可能很慢,并行运行它们可以提高效率。

问题是,每当所有令牌过期并且需要交互式登录时,所有并行请求都属于 aquireTokenPopup 的范围,并且只有其中一个正在工作,另一个则失败并出现 interaction_in_progress 错误。

MSAL 文档说 aquireTokenSilent

returns currently processing promise if parallel requests are made
- 为什么 aquireTokenPopup 的情况并非如此?

https://learn.microsoft.com/en-us/javascript/api/@azure/msal-browser/publicclientapplication?view=msal-js-latest#method-details

处理这种情况的最佳方法是什么?是否有一些库可以封装此 MSAL 调用,并且如果同时进行多个调用(如果 MSAL 本身没有执行此操作),则仅启动一个调用?或者我是否遗漏了某些内容,并且从 axios 请求拦截器中调用 MSAL 根本不是一个好主意?

javascript axios openid msal.js msal
1个回答
0
投票

看起来这个简单的添加解决了问题,但我仍然想知道为什么 MSAL 不这样做以及这是否是一个合适的解决方案。

private currentTokenPromise: Promise<string> | null = null;

getAccessToken() {
  if (this.currentTokenPromise) {
    return this.currentTokenPromise;
  }

  const tokenPromise = this.acquireToken().then((t) => {
    this.currentTokenPromise = null;
    return t?.accessToken || '';
  });

  this.currentTokenPromise = tokenPromise;

  return tokenPromise;
}
© www.soinside.com 2019 - 2024. All rights reserved.