使用OAuth进行Office 365 / EWS身份验证

3
我正在尝试使用OAuth和EWS Managed API登录Office 365 Exchange Online。
我已经可以连接到Office 365 Web API(REST),所以我有一个有效的令牌来自活动目录身份验证库(ADAL)。
现在,我正在尝试使用EWS和TokenCredentials进行连接。
代码很简单,我想:
public static ExchangeService ConnectToServiceWithImpersonation(string token)
{
    var service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);

    if (true)
    {
        service.TraceListener = new TraceListener();
        service.TraceFlags = TraceFlags.All;
        service.TraceEnabled = true;
    }

    var credentials = new TokenCredentials(token);

    service.Credentials = credentials;

    service.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
    return service;
}

令牌由ADAL生成,而ADAL是使用“Office 365 API工具-预览版”示例代码生成的。

// Obtain information for communicating with the service:
Office365ServiceInfo serviceInfo = Office365ServiceInfo.GetExchangeServiceInfo();
if (!serviceInfo.HasValidAccessToken)
{
    return Redirect(serviceInfo.GetAuthorizationUrl(Request.Url));
}

// Connect to Exchange
var service = ConnectToServiceWithImpersonation(serviceInfo.AccessToken);

Folder inbox = Folder.Bind(service, WellKnownFolderName.Inbox);

在调用Folder.Bind时,我收到了401未授权错误。EWS跟踪为我提供了以下信息:
2014-04-06 12:06:39.2012 TRACE ExchangeWebServices: EwsResponseHttpHeaders -> <Trace Tag="EwsResponseHttpHeaders" Tid="11" Time="2014-04-06 10:06:39Z">
HTTP/1.1 401 Unauthorized
request-id: 01ba1ca9-2850-480a-9d65-ec55bfef8657
X-CasErrorCode: BadSamlToken
X-FEServer: AMSPR04CA018
Content-Length: 0
Cache-Control: private
Date: Sun, 06 Apr 2014 10:06:39 GMT
Server: Microsoft-IIS/7.5
WWW-Authenticate: Basic Realm=""
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET

不幸的是,数小时的谷歌搜索并没有真正帮助,似乎关于EWS和OAuth身份验证的具体信息不是很多,而我不知道如何进一步进行故障排除,因此我希望有人能给出一些建议,以便让其正常工作。


是的,这并不涉及EWS Managed API,只涉及Web API(REST)。 - MichelZ
3个回答

6

在这个示例中,TokenCredentials不是正确的类。正如Jason所提到的,它是为其他原因而设置的。需要注意的是,使用此类和/或SAML令牌将无法在Exchange Online中与EWS一起使用,只支持基于OAuth的访问。为了使其工作,我们在EWS Managed API中放置了一个OAuthCredentials类。在您的代码中,您可以使用“var credentials = new OAuthCredentials(token)”进行设置。请注意,EWS Soap仅支持完整的“user_impersonation” /“完全访问用户邮箱”的权限。诸如Calendar.Read之类的细粒度权限仅适用于EWS Rest APIs。虽然“完全邮箱访问”需要管理员同意,但其他租户的管理员也可以同意,因为它是一个Web应用程序。如果您想开发本机应用程序,则必须直接在运行的租户的应用程序中注册该应用程序,以使用“完全邮箱访问”。


2
您可以使用OAuth连接到EWS(而不是REST),但是这并不太顺畅。EWS需要Azure Active Directory中的特殊“完全访问用户邮箱”的委派权限,需要管理员进行注册。此权限也不会在组织外“传播”,因此没有针对EWS的用户同意场景。基本上,唯一适用于此的情况是管理员为您自己的组织注册应用程序。
请检查Azure中的应用程序注册,并确保已分配该权限。
假设您已分配了该权限,我已经通过两种方式使其正常工作。
  1. The simplest: Just add the token you get back to the request headers in an Authorization header, like so:

    ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
    string accessToken = GetAccessToken();
    if (!string.IsNullOrEmpty(accessToken))
        service.HttpHeaders.Add("Authorization", "Bearer " + accessToken);
    
  2. More complex: Implement your own credentials class that implements the ICredentials interface. Pass this class into the constructor of the Microsoft.Exchange.WebServices.Data.OAuthCredentials class, and assign the new OAuthCredentials object to the Url property of the ExchangeService object.

分配了“完全访问用户邮箱(预览版)”。是的,我知道它需要管理员权限,这没有问题。该应用仅由管理员操作,不是终端用户应用。 - MichelZ
啊,好的。那么我怀疑TokenCredentials类没有做正确的事情。你有查看网络跟踪并确认令牌是否在Authorization: Bearer头中发送吗? - Jason Johnston
我还没有。我会看看能否捕获追踪并回复你。 - MichelZ
我研究了一下TokenCredentials类,这不是正确的方法。那个类是一段时间以前添加的,用于支持SAML令牌,而不是OAuth。我会在上面的答案中加入更多信息。 - Jason Johnston
只是提供信息:Fiddler跟踪显示它没有在Authorization: Bearer头中使用令牌,但它是EWS请求本身的一部分。(或者确切地说是SOAP头) - MichelZ

0

如果您来自aad的认证域,则可以使用saml,并使用ms在线sts交换该令牌。我做到了这一点,我的技术文档在网上很容易找到。

有兴趣放弃所有这些,现在使用aad发行的访问令牌。

旧模型在某些方面很可爱,因为您不会将自己的应用程序与aad oauth绑定,只有在与微软属性交互时才会与aad land绑定。如果使用openid connect,具有供应商移动令牌(tgt,除名称外),也许我可以接受一些代码依赖关系。

所以,我有一个aad(netmagic.onmicrosoft.com),带有经过认证的域注册(rapmlsqa.com)。我是否可以在aad中创建一个webapi类应用程序,将office权限分配给它?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接