Azure AD OAuth2访问令牌请求错误 - 400错误请求。

5

我的WPF桌面应用程序(C#)试图通过Microsoft Graph API读取用户的Outlook电子邮件。我卡在了身份验证过程中;我已经收到了身份验证代码,现在我正在尝试从Azure获取访问令牌,但是每当发送请求以获取访问令牌时,都会收到HTTP 400错误代码:

/**** Auth Code Retrieval ****/
string authCodeUrl = "https://login.microsoftonline.com/common/oauth2/authorize";
authCodeUrl += "?client_id" = clientId;
authCodeUrl += "&redirect_uri=" + redirectUri;
authCodeUrl += "&response_type=code";
authCodeUrl += "&resource=https%3A%2F%2Fgraph.microsoft.com%2F";
Process.start(authUrl); // User logs in, we get the auth code after login
string code = "......"; // Hidden for this post

/**** Access Token Retrieval ****/
string tokenUrl = "https://login.microsoftonline.com/common/oauth2/token"
string content = "grant_type=authorization_code";
content += "&client_id=" + clientId;
content += "&resource=https%3A%2F%2Fgraph.microsoft.com%2F";
content += "&code=" + code;
content += "&redirect_uri=" + redirectUri;
WebRequest request = WebRequest.Create(tokenUrl);
request.ContentType = "application/x-www-form-urlencoded";
byte[] data = Encoding.UTF8.GetBytes(content);
request.ContentLength = data.Length;
request.Method = "POST";
try 
{
  using (Stream stream = request.GetRequestStream())
  {
    stream.Write(data, 0, data.Length);
  }
  WebResponse response = request.GetResponse(); // This throws exception
}
catch (Exception error) // This catches the exception
{
  Console.WriteLine(error.Message); // Outputs 400, bad request
}

上面的代码用于检索授权代码,然后尝试检索访问令牌。我们没有客户机密,因为机密仅适用于 Web 应用程序,而这是一款本地桌面 WPF 应用程序。我已经阅读过许多在线教程和官方文档,主要包括官方 Graph 授权文档,但我仍然无法弄清楚自己做错了什么。如有任何帮助,将不胜感激,谢谢。
2个回答

9

我使用Fiddler调试请求,发现完整的错误信息为:用户或管理员未同意使用该应用程序。我在Google上搜索了一下这个消息,并找到了一些堆栈文章和GitHub问题线程,它们引导我找到了解决方案:我的请求一直在使用“common”作为租户ID的基本URL,但实际上我需要使用通过Stack上的答案获取的Azure租户ID。我的身份验证请求的新基本URL现在看起来像:

https://login.microsoftonline.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/oauth2/authorize 

其中“xxxx-....xxx”将被替换为您的Azure租户ID!


1
如果您不使用客户端密钥,则需要配置您的租户以支持隐式授权流。您可以按照this博客文章中的说明执行/验证配置。这需要使用Azure管理门户下载、修改应用程序清单并上传。
或者,可能更好的策略是将您的代码切换到使用汇合的v2.0身份验证终结点。它允许使用新应用程序注册门户管理您的应用程序,并很好地支持隐式流和动态范围。您可以在此处找到有关实际身份验证流的更多信息。它距离您现在所做的不远,并且只需要进行一些小的调整。
如果您在此之后仍然遇到问题,请再次联系我们。Fiddler/网络跟踪将非常有帮助。此外,异常中的详细消息也将非常有帮助。

请提供完整的400错误消息(或者像Robert说的那样,提供完整的Fiddler跟踪)。此外,请确保您的应用程序已注册为本地客户端(或公共客户端),而不是Web应用程序。本地/公共客户端不需要秘密来兑换访问令牌的代码。 - Dan Kershaw - MSFT
谢谢你们两个的回复!Fiddler帮助我解决了400错误问题 - 结果发现我的授权码已过期。现在我面临一个新问题,即访问令牌响应不是包含访问令牌的json对象(像我预期的那样),而是一个HTML文档。这是Fiddler跟踪:https://drive.google.com/file/d/0B9w2-YCX6qYvZmxXdERjWDJsamM/view?usp=sharing - mattyb
那个调用似乎是对/authorize端点的POST请求。你应该对/token端点进行POST请求,将授权码转换为访问令牌。 - Robert Anderson - Microsoft
哦,哇,是的,那只是一个微不足道的错误,谢谢。真正的错误在这里:https://drive.google.com/file/d/0B9w2-YCX6qYvSm5jUzZicFJpMmc/view?usp=sharing - mattyb
我一直在关注这篇文章的解决方案:https://dev59.com/UlsW5IYBdhLWcg3wm4UK但是我仍然遇到了400错误,我已经在批准的答案上进行了评论。 - mattyb
好的,我解决了这个问题,我之前发送请求时使用的是“common”作为租户ID,但实际上我需要用我的真实租户ID替换它! - mattyb

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