使用 OAuth 令牌验证和获取 EWS 数据

Posted

技术标签:

【中文标题】使用 OAuth 令牌验证和获取 EWS 数据【英文标题】:Authenticate and fetch EWS data using OAuth token 【发布时间】:2016-11-28 09:11:05 【问题描述】:

我正在尝试使用 EWS-java-api 构建一个 android 应用程序,以使用适用于 android 的 Active Directory 身份验证库为 office365 用户获取带有 oAuth2 令牌的 EWS 数据。类似于本文中针对 .net 显示的内容。 下面是代码:

// Code to acquire token after registering the native application in Azure active directory

authenticationContext.acquireToken(<activity context>, 
"<resource id: copied from the manifest file tag <resourceAppId> of Azure active directory after adding permission>", 
"<Application id of the registered app in AAD>", 
"<Application Redirect URI>", email, PromptBehavior.Always, "", AuthenticationCallback);

//We receive AuthenticationResult object containing authentication token in AuthenticationCallback onSuccess method and then call an async task to fetch EWS data

ExchangeService exchangeService = new ExchangeService();
exchangeService.setTraceEnabled(true);
exchangeService.getHttpHeaders().put("Authorization", "Bearer " + mAuthenticationResult.getAccessToken());
exchangeService.setUrl(URI.create("https://outlook.office365.com/EWS/Exchange.asmx"));

我能够获得 oAuth 令牌,但我无法接收交换数据,它在使用以下代码获取数据时给了我未经授权和被禁止的访问。

CalendarFolder calendarFolder = CalendarFolder.bind(service, WellKnownFolderName.Calendar); 
findResults = calendarFolder.findAppointments(new CalendarView(startDate, endDate));

另外,我不确定我在 azure 门户中设置的配置。如果您能告诉如何设置 Azure AD 应用程序以通过 android 中的 oAuth 身份验证获取 EWS 数据,那就太好了。

编辑:

以下是我的访问令牌的声明:

这是我为访问令牌获取的 JSON。并使用此访问令牌,我得到的错误是访问日历文件夹时出现 401 未经授权的访问。

JSON: 
typ: "JWT",
alg: "RS256",
x5t: "RrQqu9rydBVRWmcocuXUb20HGRM",
kid: "RrQqu9rydBVRWmcocuXUb20HGRM"
.

aud: "6ae5db95-0af3-45b6-afce-17851abc9d55",
iss: "https://sts.windows.net/06d03691-efd5-43c5-8ec9-81e57c75f63c/",
iat: 1480554267,
nbf: 1480554267,
exp: 1480558167,
acr: "1",
amr: [
"pwd"
],
appid: "410db643-4efc-4dac-8e6f-bbf05da561e1",
appidacr: "0",
e_exp: 10800,
family_name: "Dhingra",
given_name: "Surbhi",
ipaddr: "112.110.19.113",
name: "Surbhi Dhingra",
oid: "52c73152-0add-4e68-8d60-54c03a35a4b9",
platf: "1",
scp: "user_impersonation",
sub: "hUaeKxiMI-m7nNNo2c5kMYd501Blw5QQ9SNPnP1Ei_c",
tid: "06d03691-efd5-43c5-8ec9-81e57c75f63c",
unique_name: "surbhi.dhingra@<onmicrosoft domain>.com",
upn: "surbhi.dhingra@<onmicrosoft domain>.com",
ver: "1.0"
.

错误日志:microsoft.exchange.webservices.data.core.exception.service.remote.ServiceRequestException:请求失败。请求失败。远程服务器返回错误:(401)Unauthorized 在 microsoft.exchange.webservices.data.core.request.SimpleServiceRequestBase.internalExecute(SimpleServiceRequestBase.java:74) W/System.err:在 microsoft.exchange.webservices.data.core.request.MultiResponseServiceRequest.execute(MultiResponseServiceRequest.java:158) W/System.err:在 microsoft.exchange.webservices.data.core.ExchangeService.bindToFolder(ExchangeService.java:504) 在 microsoft.exchange.webservices.data.core.ExchangeService.bindToFolder(ExchangeService.java:523) 在 microsoft.exchange.webservices.data.core.service.folder.CalendarFolder.bind(CalendarFolder.java:60) 在 microsoft.exchange.webservices.data.core.service.folder.CalendarFolder.bind(CalendarFolder.java:108)

【问题讨论】:

您能否分享一下您收到的具体错误消息,以及出现在您的访问令牌中的声明?您可以使用这样的网站从原始访问令牌中提取声明:calebb.net 我最初的猜测是访问 EWS 数据确实需要在您的客户端应用程序上进行一定数量的设置,而您似乎还没有完成。我上面要求的信息应该有助于澄清这一点。 @ShawnTabrizi:感谢您的帮助,这是我获取访问令牌的 JSON。并使用此访问令牌,我得到的错误是访问日历文件夹时出现 401 未经授权的访问。 【参考方案1】:

似乎有一个已回答的 SO 线程 EWS error message: "403: Forbidden - Not enough scopes" 与您的问题类似。

只有 Office 365 REST API 支持精细访问,例如“从所有邮箱读取和写入电子邮件”。对于 EWS,您需要“使用具有对所有邮箱的完全访问权限的 Exchange Web 服务”的权限。如果您在查找此权限时遇到问题,请告诉我们。

所以你需要在管理门户的Azure AD中移动到你的应用程序的CONFIGURE选项卡,然后将Office 365 Exchange Online权限添加到你的应用程序并启用Use Exchange Web Services with full access to all mailboxes,最后保存你的配置,请看步骤和如下图。

    在 Azure AD 中移动到应用程序的 CONFIGURE 选项卡

    Office 365 Exchange Online 权限添加到您的应用程序

    启用Use Exchange Web Services with full access to all mailboxes

    保存您的配置。

【讨论】:

我已经用错误日志编辑了我的答案,请仔细阅读它们。我无法访问 Azure 经典门户,但我正在添加新门户的权限。我正在生成 2 个应用程序,一个是 Native 和一个 web api,在 web api 应用程序中,我正在添加 office 365 在线交换,并启用了完全访问权限,如您的答案所示。我在我的本机应用程序权限中添加了这个 Web api 应用程序,并使用由此生成的相同资源 ID。不过,我收到了未经授权的错误。我也在 Web api 应用程序中生成一个密钥,我在我的代码中使用 SecretKeyFactory。【参考方案2】:

感谢您提供访问令牌。 问题似乎是您为错误的受众(资源)获取了令牌。

如果您查看您的令牌,您会看到有一个“aud”声明,它定义了应该接受您的访问令牌的资源。

调用 Exchange 时,您应该有资源的令牌:“https://outlook.office.com”

您拥有的令牌似乎是针对特定 App ID 的,可能是您在自己的租户中拥有的应用之一。

请在此处查看我们公开的各种邮件 API 的参考信息: https://msdn.microsoft.com/en-us/office/office365/api/mail-rest-operations

并在此处查看我们的示例: https://dev.office.com/code-samples#?filters=exchange,outlook

我希望这会有所帮助!

【讨论】:

以上是关于使用 OAuth 令牌验证和获取 EWS 数据的主要内容,如果未能解决你的问题,请参考以下文章

使用 EWS 和 OAuth 2 的 Office 365 日历 API

oauth2 身份验证成功后获取 404 和匿名令牌

EWS 身份验证:OAuth 的服务帐户凭据

Spring Security OAuth 2:如何在 oauth/token 请求后获取访问令牌和附加数据

OAuth2RestOperations 使用从请求标头获取的令牌,而不是请求身份验证服务器

从 JWT 令牌获取 UserInfo 信息并在 Spring Boot OAuth2 自动配置上仅使用 JWK 验证