【发布时间】:2016-12-05 01:24:46
【问题描述】:
这是在多租户 Web 解决方案的上下文中,该解决方案旨在通过调用 REST API 为其用户提供对 Office 365 日历记录的访问权限。用户需要通过 Azure AD 进行身份验证才能获得访问权限。
这就是我正在做的。
0 ============= Windows Azure 测试帐户设置和应用程序已注册
我使用最初在 Gmail 上创建的测试电子邮件在 Windows Azure(可能与 Office 365 结合使用)上设置了一个帐户。
我已在 Windows Azure Active Directory 中注册了我的应用程序,并为该应用程序提供了所有可能的访问权限。基本上添加了所有可能的资源,然后为每个资源打勾。客户端密钥也已发布。
1 ============= 将浏览器重定向到 Microsoft 登录页面
在我的 jabascript 代码中,构造了以下 URL:
var url = 'https://login.microsoftonline.com/'
+ {tenant}
+ '/oauth2/authorize'
+ '?response_type=code'
+ '&client_id=' + {application_id}
+ '&redirect_uri=' + encodeURI({response_page_url})
+ '&state=' + {guid_1}
+ '&nonce=' + {guid_2}
;
然后重定向发生:
window.location.replace(url);
2 ============= 发生 Microsoft 登录
浏览器打开 Microsoft 登录页面,该页面要求输入用户电子邮件和密码。一旦输入用户电子邮件并将焦点更改为密码,页面突然翻转到其他内容并再次要求输入电子邮件,然后输入密码。很棒的可用性微软!
3 ============= 返回登录完成页面
Microsoft 登录过程结束后,浏览器将登陆我的 http://localhost:5000/something 页面,并在查询字符串中包含一些参数。
我从查询字符串中提取“状态”、“会话状态”和“代码”并将其传递给服务器以执行下一步。
4 ============= 试图为“代码”检索“id_token”
在服务器端,具体而言,在 C# 代码中,我试图通过以下请求从 Microsoft AD 获取“access_code”和“id_token”:
var url = "https://login.windows.net/common/oauth2/token";
var post = "grant_type=authorization_code"
+ "&code=" + {code_received_at_previous_step}
+ "&redirect_uri=" + HttpUtility.UrlEncode({same_redirect_url_as_before})
+ "&client_id=" + {application_id}
+ "&client_secret=" + {secret_key_issued_by_azure_ad}
+ "&resource=" + HttpUtility.UrlEncode("https://outlook.office365.com")
;
byte[] postData = new UTF8Encoding().GetBytes(post);
var request = WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postData.Length;
using (var os = request.GetRequestStream())
{
os.Write(postData, 0, postData.Length);
}
WebResponse response;
bool isError = false;
try
{
response = request.GetResponse();
}
catch (WebException up)
{
isError = true;
response = up.Response;
}
string responseText = null;
using (response)
{
using (var dataStream = response.GetResponseStream())
using (var reader = new StreamReader(dataStream))
{
responseText = reader.ReadToEnd();
}
}
var json = Json.Parse(responseText);
if (isError)
{
throw new System.Exception(string.Format("{0}:{1}", json["error"], json["error_description"]));
}
在最后一步抛出异常,并提供以下详细信息:
An exception of type 'System.Exception' occurred in IdentityManagement.dll but was not handled in user code
Additional information: invalid_grant:AADSTS65001: The user or administrator has not consented to use the application with ID '{guid}'. Send an interactive authorization request for this user and resource.
Trace ID: 6fc18926-36bd-4731-a128-54fcb320718a
Correlation ID: 75a7617e-f03f-4d57-bdd2-f655dd615a2a
Timestamp: 2016-12-05 01:15:06Z
在我的情况下收到的 JSON 数据如下:
{{"error":"invalid_grant","error_description":"AADSTS65001: The user or administrator has not consented to use the application with ID '{guid}'. Send an interactive authorization request for this user and resource.\u000D\u000ATrace ID: 6fc18926-36bd-4731-a128-54fcb320718a\u000D\u000ACorrelation ID: 75a7617e-f03f-4d57-bdd2-f655dd615a2a\u000D\u000ATimestamp: 2016-12-05 01:15:06Z","error_codes":[65001],"timestamp":"2016-12-05 01:15:06Z","trace_id":"6fc18926-36bd-4731-a128-54fcb320718a","correlation_id":"75a7617e-f03f-4d57-bdd2-f655dd615a2a"}}
所以我的问题是:
我的设置、环境、代码或执行过程中缺少什么以及如何修复它?
是否有 C#/Javascript 代码通过 API 请求(不是对某些库的功能调用)成功从 Office 365 获取日历事件的工作示例?
有没有人可以通过 Skype 或其他方式与我取得联系以帮助我使我的示例正常运行?
非常感谢提前!
非常感谢您的关注。
【问题讨论】:
-
在这里按照我的回答做管理员同意:stackoverflow.com/a/40111112/1658906你只需要做一次。
-
谢谢你,这对我来说确实让事情提前了一点。为自己点赞!在步骤 1 中将“&prompt=admin_consent”添加到 URL 更改了 Microsoft 登录过程的行为。它已要求确认权限。不幸的是,这对我来说还没有结束,因为它返回到我的页面并显示以下错误:{my_post_login_redirect_page}?error=server_error&error_description=AADSTS50000%3a+There+was+an+error+issuing+a+token .+AADSTS90092%3a+Non-retryable+error+has+occurred... 像往常一样,Microsoft 没有解释如何改善这种情况。