0

This is in context of multi-tenanted web solution, which intends to provide its users access to Office 365 calendar records via making REST API calls. User will be required to authenticate with Azure AD in order to have access.

This is what I'm doing.

0 ============= Windows Azure test account setup and Application is registered

I have set up an account on Windows Azure (presumably coupled with Office 365), using test e-mail that was initially created on Gmail.

I have registered my application within Windows Azure Active Directory, and provided this application with all access permissions possible. Basically added all possible resources and then ticked all the boxes for each. Client Secret key has also been issued.

1 ============= Redirecting Browser to Microsoft Login page

In my jabascript side of code, the following URL is constructed:

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}
;

Then redirection happens:

window.location.replace(url);

2 ============= Microsoft Login happens

Browser opens the Microsoft Login page, which asks for user e-mail and password. Once user e-mail is typed in and focus is changed to password, the page suddenly flips to something else and asks for e-mail again, and the for the password. Great Usability Microsoft!

3 ============= Back to Login Completion page

Once Microsoft Login procedure is over, browser lands to my http://localhost:5000/something page with some arguments in the query string.

I extract "state", "session_state", and "code" from the query string and pass it to server to do the next step.

4 ============= Trying to retrieve "id_token" for the "code"

On the server side, in C# code to be specific, I am trying to acquire "access_code" and "id_token" from Microsoft AD by the following request:

       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"]));
        }

At the last step an Exception is thrown with the following details:

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 data received in response in my case is the following:

{{"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"}}

So my questions are:

  1. What is missing from my setup, environment, code or the execution AND how to fix it?

  2. Is there a working example of C#/Javascript code that is successfully getting say calendar events from Office 365 via API requests (not functional calls to some libraries)?

  3. Is there anyone who cal get in touch via Skype or something to help me with making my example working?

Great thanks is advance!

Much appreciate your attention.

Gnumster
  • 11
  • 3
  • Do admin consent per my answer here: http://stackoverflow.com/a/40111112/1658906 You only need to do it once. – juunas Dec 05 '16 at 07:20
  • Thank you juunas, that has definetely moved the things a bit ahead for me. Kudos to yourself! Adding "&prompt=admin_consent" to the URL at step 1 changed the behavor of Microsoft Login procedure. It has asked to confirm permissions. Unfortunately that wasn't the end of the ordeal for me, as it returned back to my page with the following error: {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, as usually, doesn't explain what to do to refine the situation. – Gnumster Dec 05 '16 at 17:20

1 Answers1

0

It may be that you are requesting a scope that requires an administrator to consent, in which case an administrator for the organization must sign in and approve your app. The different scopes and whether they require administrative consent are here: https://graph.microsoft.io/en-us/docs/authorization/permission_scopes

Or possibly you aren't requesting any scopes at all? I don't see it in your URLs.

lgaud
  • 2,430
  • 20
  • 30
  • Thank you Igaud, I was trying to replace "resource" with "scope" and make it equal to diferent things like "Calendar.Read" etc. Same result there was. – Gnumster Dec 05 '16 at 01:40