Microsoft Graph On-Behalf-Of令牌是否仅可单次使用?
先给你明确核心结论:On-Behalf-Of(OBO)令牌绝对不是一次性使用的——只要在令牌的有效期内(通常1小时左右),完全可以重复调用Microsoft Graph API。所以你遇到的问题,100%是代码逻辑的问题,和令牌本身无关。
问题根源拆解
你修改后的Promise调用链里,第一个.then((serverSideToken) => { return useServerSideToken(serverSideToken); })执行完后,下一个.then拿到的serverSideToken其实是undefined!
为什么会这样?因为你的useServerSideToken函数在处理完Graph响应后,只调用了display方法,但没有返回任何值(更没有返回传入的令牌)。在Promise链中,每个.then的返回值会自动作为下一个.then的参数,所以当useServerSideToken没有返回令牌时,下一个.then拿到的就是undefined——用undefined作为Bearer令牌去请求Graph,必然会返回401未授权。
哪怕你调换调用顺序,第二次调用依然会拿到undefined的令牌,所以结果还是一样的。
解决方案
只需要修改你的两个Graph调用函数,让它们在处理完响应后返回传入的令牌,这样Promise链就能正确传递令牌了:
修改useServerSideToken函数(假设原函数是调用/me接口):
function useServerSideToken(token) { display("3. Call https://graph.microsoft.com/v1.0/me with the server side token"); return fetch("https://graph.microsoft.com/v1.0/me", { method: 'GET', headers: { "accept": "application/json", "authorization": "bearer " + token }, mode: 'cors', cache: 'default' }) .then((response) => { if (response.ok) { return response.json(); } else { throw (`Error ${response.status}: ${response.statusText}`); } }) .then((profile) => { display(JSON.stringify(profile, undefined, 4), 'pre'); return token; // 关键:返回令牌,供下一个then使用 }); }
同样修改useServerSideTokenAgain函数:
function useServerSideTokenAgain(token) { display("4. Call https://graph.microsoft.com/v1.0/me/messages with the server side token"); return fetch("https://graph.microsoft.com/v1.0/me/messages?$select=sender,subject", { method: 'GET', headers: { "accept": "application/json", "authorization": "bearer " + token }, mode: 'cors', cache: 'default' }) .then((response) => { if (response.ok) { return response.json(); } else { throw (`Error ${response.status}: ${response.statusText}`); } }) .then((profile) => { display(JSON.stringify(profile, undefined, 4), 'pre'); return token; // 同样返回令牌,后续调用也能正常使用 }); }
修改后,Promise链里的每个.then都能正确接收到有效的令牌,两次Graph调用都会用合法的Bearer令牌请求,就不会再出现401的问题了。
你也可以在第二次调用前加个console.log(serverSideToken)验证一下,修改前应该会打印undefined,修改后会打印有效的令牌字符串,这也能直观确认问题所在。
内容的提问来源于stack exchange,提问作者Hilton Giesenow

