Azure AD OAuth2 Access Token Request Error - 400 B

2019-02-20 15:17发布

My WPF desktop application (C#) is attempting to read the user's Outlook emails through the Microsoft Graph API. I am stuck in the authentication process; I've already received an authentication code and now I'm trying to get an access token from Azure but keep getting a HTTP 400 error code when sending out the request for the access token:

/**** 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
}

The above is the code used to retrieve the auth code followed by the attempt to retrieve the access token. We do not have a client_secret because secrets are only for Web applications and this is a native desktop WPF application. I have read that this isn't an issue though. I have followed many tutorials and official docs online, mainly the official Graph authorization doc and I still cannot figure out what I am doing wrong. Any help would be greatly appreciated, thank you.

2条回答
放我归山
2楼-- · 2019-02-20 15:58

I used fiddler to debug the request and I found the full error message: The user or administrator has not consented to use the application. I googled this message for a bit and found some stack articles and github issue threads that lead me to the solution: my request had been using "common", in the base URL, as the tenant ID when actually I needed to use my Azure tenant ID which I acquired through this answer on stack. My new base URL for the authentication requests now looks like:

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

where "xxxx-....xxx" would be replaced by your Azure tenant id!

查看更多
看我几分像从前
3楼-- · 2019-02-20 16:13

If you don't use a client secret, then you need to configure your tenant to support implicit grant flow. You can follow the directions from this blog post to perform / validate the configuration. This requires using the Azure management portal to download, modify the app manifest, and upload it.

Alternatively, and possibly a better strategy, is to switch your code over to using the converged v2.0 authentication endpoints. It allows management of your application using the new app registration portal and nicely supports implicit flow and dynamic scopes. You can find more information about the actual authentication flow here. It isn't far from what you are doing now and requires only a few small tweaks.

If you are still having issues after this, please reach out again. A fiddler / network trace would be very helpful. Also, the detailed message inside the exception would also be very helpful.

查看更多
登录 后发表回答