Search code examples
c#oauth-2.0adaloffice365api

Office365 REST API returns Unauthorized with C# ADAL


I'm building a WPF-App. First get Events and later on create Events via O365 RestAPI.

I'm able to get events with:

result = await authContext.AcquireTokenAsync(graphResourceId, clientId, redirectUri, new PlatformParameters(PromptBehavior.Auto));Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
                    string today = DateTime.Today.ToString("yyyy-MM-dd", CultureInfo.CurrentCulture);
                    string graphRequest = String.Format(CultureInfo.CurrentCulture, "https://outlook.office365.com/api/v2.0/me/calendarview?startDateTime=" + today + "T00:00:00&endDateTime=" + today + "T23:59:00&$select=Subject,organizer,start,end,attendees&$orderby=start/datetime%20asc");
                    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, graphRequest);
                    request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
                    request.Headers.Add("Prefer", "outlook.timezone=\"W. Europe Standard Time\"");
                    HttpResponseMessage response = HttpClient.SendAsync(request).Result;

                    if (!response.IsSuccessStatusCode)
                        throw new WebException(response.StatusCode.ToString() + ": " + response.ReasonPhrase);

But when I try to create Events, I will receive a "Unauthorized" using the same Token. My App have permissions to read and write calenders.

This is my code:

string postBody = "{'Subject':" + "'Discuss the Calendar REST API'," +
                            "'Body':{ " +
                                          "'ContentType':'HTML'," +
                              "'Content': 'I think it will meet our requirements!'},"
                           + "'Start': { DateTime: '" + 
                              start + "',"
                                    + " 'TimeZone': 'W. Europe Standard Time'}," +
                               "'End':{'DateTime': '" + end + "'," +
                                    "'TimeZone': 'W. Europe Standard Time'},"
                                + "'Attendees':[{" +
                                "'EmailAddress':{"
                                 + "'Address': '" + MailTB.Text + "'"
                                + 
                                " },"
                                + "'Type': 'Required'}]}";


    var emailBody = new StringContent(postBody, System.Text.Encoding.UTF8, "application/json");
        AuthenticationContext authContext = new AuthenticationContext(authority, new FileCache());
        AuthenticationResult result = await authContext.AcquireTokenAsync(graphResourceId, clientId, redirectUri, new PlatformParameters(PromptBehavior.Auto));

        Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
    string today = DateTime.Today.ToString("yyyy-MM-dd", CultureInfo.CurrentCulture);
    string graphRequest = String.Format(CultureInfo.CurrentCulture, "https://outlook.office365.com/api/v2.0/me/events");
    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, graphRequest);
    request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
    request.Headers.Add("Prefer", "outlook.timezone=\"W. Europe Standard Time\"");
        HttpResponseMessage response = MainWindow.HttpClient.PostAsync(graphRequest, emailBody).Result;

        if (!response.IsSuccessStatusCode)
            throw new WebException(response.StatusCode.ToString() + ": " + response.ReasonPhrase);

Solution

  • HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, graphRequest); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken); request.Headers.Add("Prefer", "outlook.timezone=\"W. Europe Standard Time\""); HttpResponseMessage response = MainWindow.HttpClient.PostAsync(graphRequest, emailBody).Result;

    The code you you send the post request will not send the headers you set since all the headers are set for the request parameter but you were not using it in the post.

    To send the post with access_token, you can refer code below:

    var httpClient = new HttpClient();
    httpClient.DefaultRequestHeaders.Authorization= new AuthenticationHeaderValue("Bearer", accessToken);
    httpClient.DefaultRequestHeaders.Add("Prefer", "outlook.timezone=\"W. Europe Standard Time\"");
    HttpResponseMessage response = httpClient.PostAsync(graphRequest, emailBody).Result;