Ole*_*sii 7 c# exchangewebservices oauth-2.0 office365
我在 Azure VM 上有一个 Exchange Online 环境和服务/daemin(无交互用户)应用程序。服务使用 EWS 托管 API 来处理任何租户用户邮箱中的电子邮件。现在 EWS 客户端使用基本身份验证,据 Microsoft 称,EWS 将不支持该身份验证来访问 Exchange Online。
因此,我需要找到一种方法来获取服务/守护程序应用程序的有效访问令牌以与 EWS 托管 API 一起使用。
以下文章展示了将 OAuth 2.0 与 EWS 托管 API 结合使用的示例。此示例有效,但它使用了不适合服务/守护程序应用程序场景的交互式方法来获得同意(出现登录表单,允许用户验证自己并授予应用程序请求的权限),因为没有交互式用户。
对于服务/守护程序应用程序,我需要使用client credential身份验证流程。
使用https://aad.portal.azure.com门户上的管理员帐户,我向 Azure Active Directory 注册了应用程序。为已注册的应用程序添加了客户端机密。
上述文章使用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在调试中设置变量(请参阅帖子后面的代码片段)。
我尝试了不同的端点来获取访问令牌。
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
Run Code Online (Sandbox Code Playgroud)
发送此请求会产生以下错误响应:
AADSTS70011:提供的请求必须包含“范围”输入参数。为输入参数“范围”提供的值无效。范围https://outlook.office.com/EWS.AccessAsUser.All无效。
我尝试更改scope为https://outlook.office.com/.default. 访问令牌已返回,但它似乎对 EWS 无效。EWS 客户端使用以下x-ms-diagnostics响应标头值引发 401 错误:
2000008;reason="令牌不包含权限,或者权限无法理解。";error_category="invalid_grant"
POST: https://login.microsoftonline.com/<TENANT_ID>/oauth2/token
grant_type=client_credentials
client_id=***
client_secret=***
resource=https://outlook.office.com
Run Code Online (Sandbox Code Playgroud)
访问令牌已返回,但似乎对 EWS 无效。EWS 客户端抛出 401 错误,x-ms-diagnostics响应标头的值与#1 中描述的相同。
这是我用来使用 Postman 中获取的访问令牌测试 EWS 客户端的代码示例:
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
Run Code Online (Sandbox Code Playgroud)
我们遇到了类似的问题:我们想使用服务帐户连接到单个邮箱,然后仅使用 EWS API 执行一些操作(例如在 GAL 中搜索),这full_access_as_app似乎有点矫枉过正。幸运的是,这是可能的:
遵循正常的“委托”步骤
并使用它通过用户名/密码获取令牌:
...
var cred = new NetworkCredential("UserName", "Password");
var authResult = await pca.AcquireTokenByUsernamePassword(new string[] { "https://outlook.office.com/EWS.AccessAsUser.All" }, cred.UserName, cred.SecurePassword).ExecuteAsync();
...
Run Code Online (Sandbox Code Playgroud)
通过该设置,我们可以使用“传统”用户名/密码方式,但使用 OAuth 和 EWS API。