【发布时间】:2025-11-27 03:25:05
【问题描述】:
场景
我在 Azure VM 上有一个 Exchange Online 环境和服务/守护程序(无交互式用户)应用程序。服务使用 EWS 托管 API 处理 any 租户用户邮箱中的电子邮件。现在 EWS 客户端使用基本身份验证,根据 Microsoft 的说法,EWS 将不支持访问 Exchange Online。
问题/问题
因此,我需要找到一种方法来获取服务/守护程序应用程序的有效访问令牌,以便与 EWS 托管 API 一起使用。
我的发现
以下article 显示了将 OAuth 2.0 与 EWS 托管 API 结合使用的示例。此示例有效,但它使用了获取同意的交互式方法(出现登录表单,允许用户验证自己并向应用程序授予请求的权限),不适合服务/守护程序应用场景,因为没有交互式用户。
对于服务/守护程序应用程序,我需要使用client credential 身份验证流程。
注册申请
在https://aad.portal.azure.com 门户上使用管理员帐户我向 Azure Active Directory 注册了应用程序。为已注册的应用程序添加了客户端密码。
上述article 使用https://outlook.office.com/EWS.AccessAsUser.All 作为scope。但我没有在门户网站上找到此类 URL 的许可。在Office 365 Exchange Online>Application permissions>Mail下发现只有以下权限:
-
https://outlook.office365.com/Mail.Read允许应用在没有登录用户的情况下阅读所有邮箱中的邮件 -
https://outlook.office365.com/Mail.ReadWrite允许应用在没有登录用户的情况下创建、阅读、更新和删除所有邮箱中的邮件。
我添加了它们并为所有用户授予了管理员同意。
获取访问令牌
出于测试目的和简单性,我没有使用任何身份验证库(ADAL、MSAL 等)。我使用 Postman 获取访问令牌,然后在调试中设置 token 变量(参见帖子后面的代码 sn-p)。
我尝试了不同的端点来获取访问令牌。
- OAuth 2.0 令牌端点 (v2)
POST: https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/token
grant_type=client_credentials
client_id=***
client_secret=***
scope=https://outlook.office.com/EWS.AccessAsUser.All
发送此请求会产生以下错误响应:
AADSTS70011:提供的请求必须包含“范围”输入参数。为输入参数“范围”提供的值无效。范围https://outlook.office.com/EWS.AccessAsUser.All 无效。
我尝试将scope 更改为https://outlook.office.com/.default。访问令牌已返回,但它似乎对 EWS 无效。 EWS 客户端抛出 401 错误,x-ms-diagnostics 响应标头值如下:
2000008;reason="令牌不包含权限,或权限无法理解。";error_category="invalid_grant"
- OAuth 2.0 令牌端点 (v1)
POST: https://login.microsoftonline.com/<TENANT_ID>/oauth2/token
grant_type=client_credentials
client_id=***
client_secret=***
resource=https://outlook.office.com
访问令牌已返回,但似乎对 EWS 无效。 EWS 客户端抛出 401 错误,x-ms-diagnostics 响应标头的值与 #1 中所述的相同。
将获取的访问令牌与 EWS 托管 API 一起使用
这是我用来测试 EWS 客户端的代码示例,其中使用了在 Postman 中获取的访问令牌:
var token = "...";
var client = new ExchangeService
{
Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx"),
Credentials = new OAuthCredentials(token),
ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress,
"user@domain.onmicrosoft.com"),
};
var folder = Folder.Bind(client, WellKnownFolderName.SentItems);
【问题讨论】:
-
我会假设使用客户端凭据或基于证书的身份验证,这些是特定于租户的。如果它是唯一一个可以的租户,但如果您需要支持任何人都可以用来访问他们自己的租户的产品,那么您需要他们执行相同的证书/客户端流程,或使用登录流程。后者您可以在服务应用程序中存储刷新令牌以获取访问令牌。前者,我知道有一种方法可以提供一个“应用程序”,365 管理员可以在 365 中安装并连接它,但还没有研究过。
-
有人可以确认是否可以限制应用程序权限视图 EWS API 可访问的邮箱数量?
-
@Oleksii 您是否尝试过使用带有客户端 ID 和租户 ID 而不是令牌的 EWS API 进行连接
标签: c# oauth-2.0 office365 exchangewebservices