使用新的 MS Graph API 给出 AUTHENTICATE 失败的 Outlook IMAP 范围

Outlook IMAP scopes giving an AUTHENTICATE failure with new MS Graph API

我请求以下范围(URL 编码):

offline_access user.read https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send

使用新的 Microsoft Graph API 的 OAuth 2.0 授权过程似乎工作正常,但是当使用访问令牌通过 XOAuth2 连接到 IMAP 时,我得到一个 NO AUTHENTICATE,这表示令牌无效。

事实证明,这不是用户的问题,而是 Microsoft 的 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,您不能请求更大的 scope/multi-tenant 密钥,否则它不会通过 XOAuth2 进行验证。您会注意到单独为 IMAP/SMTP 返回的访问令牌总是比为其他范围返回的访问令牌小得多。

要解决此问题,您将需要请求 两个访问令牌。首先,您应该使用您的授权码在以下范围内申请密钥:

offline_access https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send

在此之后,您需要为配置文件请求访问令牌。但是,自 2020 年 10 月起,您将不再被允许使用单一授权码进行多次访问令牌授予。因此,您将需要再次登录用户——执行此操作的规范方法是简单地将他们导航回 auth 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)。