【问题标题】:Office 365 / EWS Authentication using OAuth: The audience claim value is invalid使用 OAuth 的 Office 365/EWS 身份验证:受众声明值无效
【发布时间】:2016-03-13 00:17:50
【问题描述】:

我仍在为此苦苦挣扎。 详情请看我的previous question

我正在做一个应用程序(当前是命令行),它应该通过 EWS 托管 API 访问 Office 365/Exchange。目标是通过 OAuth2 进行身份验证。

我已经在 Azure AD 中注册了一个应用程序。
我从那里使用了 ClientID
我生成了一个应用程序密钥/密钥
我已将“拥有对用户邮箱的完全访问权限(预览版)”权限委派给该应用。

我正在使用 ADAL 来检索访问令牌,如下所示:

var authority = "https://login.windows.net/<tenant>"
var authContext = new AuthenticationContext(authority);
var clientCredential = new ClientCredential("<clientId>", "<appKey>");
result = OAuthTokenManager.authContext.AcquireToken("<my ResourceID>", clientCredential);

我确实得到了一个访问令牌。解码后的值为:

{
 "typ": "JWT",
 "alg": "RS256",
 "x5t": "kriMPdmBvx68skT8-mPAB3BseeA"
}.
{
 "aud": "<my resource ID>",
 "iss": "https://sts.windows.net/2d1f889d-7930-4ef6-9f87-ef096d91ac47/",
 "nbf": 1403253608,
 "exp": 1403296808,
 "sub": "bdb0baf9-29ca-4a43-b9f8-d81ca2ae83bd",
 "appid": "<my app ID>",
 "oid": "bdb0baf9-29ca-4a43-b9f8-d81ca2ae83bd",
 "tid": "2d1f889d-7930-4ef6-9f87-ef096d91ac47",
 "idp": "https://sts.windows.net/2d1f889d-7930-4ef6-9f87-ef096d91ac47/"
}.
[signature] 

然后我使用此令牌连接到 EWS:

var service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
var credentials = new OAuthCredentials(token);
service.Credentials = credentials;
service.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "<smtp address of o365 mailbox>");
Folder inbox = Folder.Bind(service, WellKnownFolderName.Inbox);

Folder.Bind 失败并出现 401 错误。

在 EWS Trace 中,我可以将其视为原因:

The audience claim value is invalid <my resource ID>

资源 ID 是来自已注册应用程序的“APP-ID-URI”。

我确定我只是遗漏了一个小细节......但我找不到它:)
任何指针都非常感谢。

如果我使用 https://outlook.office365.com/ 作为资源 ID (aud),我会收到以下错误消息:

ACS50001: Relying party with identifier 'https://outlook.office365.com/' was not found.

租户确实有一个 Exchange 订阅,并且它拥有邮箱的完全访问权限。

【问题讨论】:

    标签: c# oauth-2.0 ms-office exchangewebservices office365


    【解决方案1】:

    嗯,好的。对于服务类型的应用程序,您将需要使用可以模拟您的用户的服务帐户。有关详细信息,请参阅this MSDN topic。拥有该帐户后,您需要通过 OAuth 作为该服务帐户进行身份验证,然后根据需要模拟您的用户。

    使用本机应用程序,you cannot use the app secret to authenticate。因此,您需要执行以下操作:

    AuthenticationResult result = authContext.AcquireToken("https://outlook.office365.com", clientId, new Uri(callbackUri), PromptBehavior.Auto);
    

    其中clientId 是您在 Azure 注册中的客户端 ID,callbackUri 是您在 Azure 中注册应用程序时指定的重定向 URI。这将导致显示提示窗口,但如果您保存令牌和刷新令牌并使用它们进行刷新,您应该避免任何进一步的提示。您取回的令牌应类似于:

    {
     "typ": "JWT",
     "alg": "RS256",
     "x5t": "kriMPdmBvx68skT8-mPAB3BseeA"
    }.
    {
     "aud": "https://outlook.office365.com",
     "iss": "https://sts.windows.net/9e4563d1-423e-493b-bdc5-9a98fe2e24d9/",
     "iat": 1403706230,
     "nbf": 1403706230,
     "exp": 1403710130,
     "ver": "1.0",
     "tid": "9e4563d1-423e-493b-bdc5-9a98fe2e24d9",
     "amr": [
      "pwd"
     ],
     "oid": "4a6e20e6-9711-4ca1-888b-34e63f65f897",
     "upn": "impersonationaccount@contoso.com",
     "unique_name": "impersonationaccount@contoso.com",
     "sub": "Pp3JW2dfYELMUBjGjUIZLarT4diOkkKZ1OJPVunzAYE",
     "puid": "100300008A9245F4",
     "family_name": "Account",
     "given_name": "Application",
     "appid": "<your app id>",
     "appidacr": "0",
     "scp": "user_impersonation",
     "acr": "1"
    }.
    [signature]
    

    应用将作为 impersonationaccount@contoso.com 用户进行身份验证,然后您可以模拟其他用户。我刚刚使用我的测试 Office 365 帐户使用一个小的测试控制台应用程序对此进行了测试。

    最后一个警告:EWS 所需的 OAuth 权限范围不像其他权限范围那样可移植。我的意思是,与 REST API 应用程序不同,您可以使用开发人员租户在 Azure 中注册它,然后其他 Office 365 组织只需同意您的应用程序,使用 OAuth 的 EWS 应用程序必须在每个应用程序中单独注册使用它们的租户。如果您正在为自己的组织创建此应用程序,那没什么大不了的。但是,如果您打算将此应用授权给其他组织,您应该注意一些事项。

    【讨论】:

    • 谢谢 Jason,我没有意识到这一点(文档似乎也不是很清楚)。那我试试这个方法,谢谢!
    • 了解文档,感谢您的反馈。我们正在编写专门将 OAuth 与 EWS 结合使用的文档。它对我们来说仍然是新事物,我什至不确定模仿是否会起作用! :)
    • 那么“提示”会提示输入密码吗? (不幸的是,这对于我们的应用类型来说毫无用处......)我们可以通过什么方式以编程方式提供 PW?
    • 不,您不能以编程方式提供它,至少我不知道! OAuth 背后的理念是您的应用永远不会拥有用户的密码。您可以在初始配置/安装期间进行某种登录以获得令牌/刷新令牌组合吗?我相信如果你这样做了,你就不必再次提示登录,只要你在刷新令牌过期之前刷新。
    • 我会想办法解决这个限制。我猜应该可以将令牌发送到另一个应用程序?我们有一个 Web UI 应用程序,可以“控制”不同机器上的服务。这些服务将需要令牌。因此我们可以在 WebUI 中提示用户输入凭据,然后将令牌发送到要使用的服务。
    【解决方案2】:

    您的“aud”参数应为“https://outlook.office365.com”。尝试将其传递给 AcquireToken。您也不需要设置 ImpersonatedUserId。希望对您有所帮助!

    【讨论】:

    • 谢谢杰森。我试过了,得到ACS50001: Relying party with identifier 'https://outlook.office365.com/' was not found.我需要冒充,他现在怎么连接到哪个邮箱? (我使用 AppId + App Secret 作为 ClientCredentials)
    • 用户身份也在令牌中。 OAuth 流程对于 EWS 有点限制,但本质上作为您获取令牌的一部分,会提示用户登录,然后将该信息封装在您返回的令牌中,或者至少在我使用简单桌面类型应用程序的经验中.您是通过网络应用执行此操作的吗?
    • 不,这是一个服务类型的应用程序。我们只有管理员同意。我们需要能够模拟每个用户
    猜你喜欢
    • 1970-01-01
    • 2019-04-17
    • 1970-01-01
    • 2020-06-19
    • 2020-11-09
    • 2016-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多