【发布时间】:2017-07-28 05:21:15
【问题描述】:
我有一个守护程序可以访问一些用户的电子邮件以便自动转发它们。我在 Azure 中注册了守护进程并请求了一些由管理员授予的应用程序权限。 然后我能够获得一个 oAuth2 令牌,并且应用程序按预期运行。
现在我的 IT 部门询问我,该应用是否可以模拟单个用户,而不是对每个邮箱拥有完全权限,以便守护程序只能读取和转发该用户的电子邮件。
所以我在 Azure 上注册了另一个应用程序,并且只为其请求了委派权限(我选择了所有不需要管理员批准的委派权限,总共 44 个)。 然后我构建了我的授权 URL 并将其发送给相关用户。用户单击该链接后,会看到应用程序请求的所有权限的列表,并同意将这些权限授予应用程序。
然后我的应用收到了一个授权码,正如预期的那样。 MS documentation 然后声明我可以使用该代码获取访问用户邮箱的令牌。因此,我使用 MS 提供的说明构建了 REST 参数:
"grant_type=authorization_code" +
"&client_id={appID}+
"&client_secret={appSecret} +
"&code={auth_code}+
"&redirect_uri={Same_Redirect_URI_used_when_obtaining_Authorization_Code} +
"&resource=https://graph.microsoft.com"
我向授权 URL 发出包含此内容的 POST 请求,如文档中所述:
https://login.microsoftonline.com/{myTenantID}/oauth2/token
现在奇怪的是,一旦我的脚本运行 xhr.send(tmpSnd); 方法(其中 tmpSnd 包含上述 REST 参数),我立即得到一个 msxml3.dll: Access is denied error。至少,我预计该错误会作为 POST 响应的一部分返回,但我什至从未通过 send() 方法。
这是我用来获取 Token 的 JS 代码:
this.getDelegatedToken = function(appEndPoint, appID, appSecret,auth_Code,appURI){
var result=null;
var GRAPH_URL_TOKEN = "https://login.microsoftonline.com/" + appEndPoint + "/oauth2/token";
xhr.open("POST", GRAPH_URL_TOKEN, false);
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
var params ="grant_type=authorization_code" +
"&client_id=" + appID +
"&client_secret=" + appSecret +
"&code=" + auth_Code+
"&redirect_uri=" +appURI +
"&resource=https://graph.microsoft.com";
xhr.send(params);
if(xhr.status==200) {
result = JSON.parse(xhr.responseText);
}
return result;
};
我想我在某处读到过,仅使用 Delegated Permissions 可能会导致守护进程出现问题,但对于我的一生,我不记得我在哪里读过它(使用 Graph 需要大量阅读!)。
编辑
如果我将 &code 参数设置为无效值,我会收到预期的错误消息(“代码格式错误或无效”)。如果我将其设置为之前已过期的授权码,我还会收到预期的错误消息(“提供的授权码或刷新码已过期”)。所以看起来我所有的 POST 参数都是有效的,因为当我故意传递一个无效的错误消息时,我会收到正确的错误消息。我只是不明白为什么,当我传递所有正确的参数时,我什至没有收到错误响应,我只收到来自 XHR 对象的 Access is denied 消息。
任何人都可以发现代码或流程中的任何明显错误吗?
【问题讨论】:
-
你是从前端 JavaScript 运行的吗?
-
我从 Windows Scripting Host 的应用内实例运行它。不涉及网络浏览器。应用程序本身作为 Windows 服务运行,这意味着不涉及 GUI。在某种程度上,它类似于 NodeJS 会做的事情。除了不是 NodeJS,它是一个 Windows 可执行文件(用 Delphi 编写),它实例化了 WSH。希望能回答你的问题。
-
只是想确认您的tenantID(名为 appEndPoint 的变量)看起来像“contoso.com”(当然对于您的组织而言)。
-
我已经尝试过使用 DNS (myprefix.myorg.com) 和 Azure 门户上显示的应用程序 ID。
-
我希望您不要混淆 v2 API 和 v1 API。令牌和代码不能在 v2 和 v1 API 之间共享