事实证明,这不是用户的问题,而是微软的 Graph API 的问题。虽然没有记录,但目前不允许您请求范围属于两个租户的令牌,否则它将选择一个并静默失败。
在这种情况下,User.Read 属于 Microsoft Graph 租户。从技术上讲,如果您的用户是组织 Outlook/Office365 用户,他们可能实际上没有安装 Microsoft Graph,正确的范围是 https://outlook.office.com/User.Read。 但是 Outlook 配置文件端点已被弃用,不建议使用(您也无法知道您的用户是否拥有 MS Graph 租户)。似乎解决了这个问题,可以在不指定 Microsoft Graph URL 的情况下请求 user.read 权限。
这基本上是您在上面所做的,但可能会产生误导,因为您实际上并未请求一般 User.Read 权限,然后可以将其解析给 Outlook 租户。实际发生的是 User.Read 权限被映射到某个默认租户,因此您的范围实际上包含多个租户(默认租户和 Outlook)。
由于这是不允许的,它会静默失败并默认为默认租户。对于他们的大多数 API,这仍然有效,但特别是对于 IMAP/SMTP,您不能请求更大的范围/多租户密钥,否则它将无法通过 XOAuth2 进行验证。您会注意到,单独为 IMAP/SMTP 返回的访问令牌总是比其他范围的访问令牌小得多。
要解决此问题,您需要申请两个访问令牌。首先,您应该使用您的授权码来请求以下范围内的密钥:
offline_access https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send
之后,您需要为配置文件请求访问令牌。但是,从 2020 年 10 月起,您不再可以使用单个授权代码来授予多个访问令牌。因此,您将需要再次登录用户 - 这样做的规范方法是简单地将他们导航回身份验证 URL,将 login_hint 字段留空。这将根据您构建 URL 的方式而有所不同,但这里有一个 JS 示例:
url = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize?'
url += `client_id=${clientId}`
url += '&response_type=code'
url += '&redirect_uri=${redirectURI}'
url += '&response_mode=query'
url += '&login_hint='
url += '&scope=offline_access%20User.Read%20https%3A%2F%2Foutlook.office.com%2FIMAP.AccessAsUser.All%20https%3A%2F%2Foutlook.office.com%2FSMTP.Send'
url += '&state=12345
请注意,对于两个访问令牌请求,您的授权代码必须请求完整范围(包括 User.Read 和 IMAP 范围,如 IMAP.AccessAsUser.All。 指定较小的范围并不能保证配置文件您阅读的内容必然与 Outlook 帐户相对应。
收到第二个授权码后(它不会要求用户再次手动登录,只需加载一点并自动解析第二个码),您可以请求具有以下范围的新访问令牌:
user.read
您可以包含上述任何其他 Graph API 范围,但在 Outlook 下,尤其是在 IMAP 下指定某些内容会混淆您的范围。响应范围仍将包含 EAS 访问和 Outlook 范围,但添加了user.read 权限。
您应该使用第二个令牌来访问配置文件并与第一个令牌分开刷新它(它应该只用于 IMAP/SMTP)。