如何获取有效令牌调用Microsoft Graph API,解决EWS令牌受众无效问题?
解决EWS令牌调用Graph API的受众无效问题及替代方案
错误原因
你遇到的Access token validation failure. Invalid audience错误,本质是EWS令牌的受众(aud字段)是EWS服务端点(比如https://outlook.office365.com/EWS/Exchange.asmx),而Microsoft Graph API要求令牌的受众必须是https://graph.microsoft.com,所以直接用EWS令牌调用Graph肯定会被拒绝。
下面是几种可行的解决办法:
方案1:令牌交换(Token Exchange)获取Graph有效令牌
通过OAuth 2.0的令牌交换流程,把你的EWS访问令牌转换成针对Graph的访问令牌,步骤如下:
- 向Azure AD的令牌端点发送POST请求,参数包括:
grant_type:urn:ietf:params:oauth:grant-type:token-exchangeclient_id: 你的Azure AD应用客户端ID(需提前注册并配置对应权限)client_secret: 应用客户端密钥(后端服务调用场景需要)subject_token: 你现有的EWS访问令牌subject_token_type:urn:ietf:params:oauth:token-type:access_tokenresource:https://graph.microsoft.com
- 成功请求后会返回针对Graph的访问令牌,用这个令牌调用
https://graph.microsoft.com/v1.0/me/messages/${itemId}/attachments/${attachmentId}即可获取附件内容。 - 注意:你的Azure AD应用需要拥有
Mail.Read的Graph权限,且EWS令牌的权限范围要覆盖对应邮件访问权限。
方案2:直接用EWS API获取附件(无需Graph)
既然你已经有合法的EWS令牌,直接用EWS API获取附件反而更直接,不用绕令牌交换:
- 用
ews-javascript-api的Node.js示例代码:
const ews = require('ews-javascript-api'); // 初始化EWS服务 const service = new ews.ExchangeService(ews.ExchangeVersion.Exchange2016); service.Credentials = new ews.OAuthCredentials(你的EWS令牌); service.Url = new ews.Uri("https://outlook.office365.com/EWS/Exchange.asmx"); // 获取附件并转Base64 async function getAttachment(attachmentId) { const attachment = await service.GetAttachment(new ews.AttachmentId(attachmentId), ews.BodyType.Text); const base64Content = Buffer.from(attachment.Content).toString('base64'); // 后续调用AWS SDK的putObject方法上传到S3即可 }
方案3:Outlook加载项前端场景直接用Office.js获取附件
如果你的流程是从Outlook加载项发起的,完全可以跳过后端的EWS/Graph调用,直接在前端用Office.js获取附件:
// 假设已拿到目标附件ID Office.context.mailbox.item.attachments.getAsync(attachmentId, function(result) { if (result.status === Office.AsyncResultStatus.Succeeded) { const attachment = result.value; // 获取附件内容 attachment.getContentAsync(function(contentResult) { if (contentResult.status === Office.AsyncResultStatus.Succeeded) { // 将ArrayBuffer转为Base64 const base64Content = btoa(String.fromCharCode(...new Uint8Array(contentResult.value))); // 可通过后端接口中转或直接用AWS SDK前端上传到S3 } }); } });
这个方案最简洁,无需处理令牌相关问题,直接利用Office.js原生能力。
内容的提问来源于stack exchange,提问作者Vishwanathan
相关产品推荐
相关产品推荐

