2

I'm having a hard time sending a POST request to the Outlook API.

I'm working on my local machine and defined the redirectUrl to my localhost:port

My GET requests works:

var apiUrl = "https://outlook.office.com/api/v2.0/me/calendarview?startdatetime=" + startDateTime + "&enddatetime=" + endDateTime + "&$top=" + 10;

$.ajax({
    type: 'GET',
    url: apiUrl,
    headers: {
        "Authorization": "Bearer " + token
    }
}).done(function (data) {
    processResults(data);
}).fail(function (response) {
    handleFailure();
});

but when I try to send a POST, I get this message :

Access is denied. Check credentials and try again.

and my code is:

var apiUrl = "https://outlook.office.com/api/v2.0/me/events";
var postData = {
  "Subject": "Plan summer company picnic",
  "Body": {
    "ContentType": "HTML",
    "Content": "Let's kick-start this event planning!"
  },
  "Start": {
      "DateTime": "2019-01-15T11:00:00",
      "TimeZone": "Pacific Standard Time"
  },
  "End": {
      "DateTime": "2019-01-15T12:00:00",
      "TimeZone": "Pacific Standard Time"
  },
  "Attendees": [
    {
      "EmailAddress": {
        "Address": "myMail@gmail.com",
        "Name": "Name Here"
      },
      "Type": "Required"
    }
  ]
};

$.ajax({
    type: 'POST',
    url: apiUrl,
    headers: {
        "Authorization": "Bearer " + token
    },
    contentType: 'application/json',
    data: JSON.stringify(postData)
}).done(function (data) {
    processResults(data); 
}).fail(function (response) {
    handleFailure();
});

In both cases I use the same token, so it's probably not a login problem. I also allowed Calendars.ReadWrite in the app.

UPDATE

I cleared the cache, logged in, made a GET call, then made a POST call, then made a GET call again. Both GET calls works, so the problem is not the token or a cache problem.

Itay Gal
  • 10,706
  • 6
  • 36
  • 75
  • 1
    Does the outlook API have any role restrictions? Like needing to allow an app to have write access vs read? I know things like GitHub have fine grained access roles for specific tokens. – zero298 Jan 14 '19 at 22:48
  • If I understood your question, then yes, but I allowed writing by adding the `Calendars.ReadWrite` Permission – Itay Gal Jan 14 '19 at 22:51
  • Might be worth checking your token hasn't expired. Perhaps the GET request results are cached which is why it continues to work. Try adding `cache: false` to the GET jQuery options – Phil Jan 14 '19 at 23:41
  • @Phil see my update, it's not a cache problem and my token was not expired. – Itay Gal Jan 15 '19 at 06:15
  • Yeah, I thought it was a longshot. Good luck figuring it out – Phil Jan 15 '19 at 06:36

1 Answers1

1

The problem was on the authentication process, apparently on each request I have to specify the scope and it should include multiple permissions.

In the headers I found this:

x-ms-diagnostics: 2000008;reason="Access to this API requires the following permissions: 'Calendars.Read.All,Calendars.Read.Shared,Calendars.ReadWrite.All,Calendars.ReadWrite.Shared'. However, the application only has the following permissions granted: 'Calendars.Read,Calendars.ReadWrite'.";error_category="invalid_grant"

Even this is wrong, since Calendars.Read.All and Calendars.ReadWrite.All doesn't exist, it should be Calendars.Read and Calendars.ReadWrite.

The authentication request should look like this:

var authUrl = authServer +
          "response_type=" + encodeURI(token) +
          "&client_id=" + encodeURI(clientId) +
          "&scope=" + encodeURI("https://outlook.office.com/Calendars.Read https://outlook.office.com/Calendars.Read.Shared  https://outlook.office.com/Calendars.ReadWrite https://outlook.office.com/Calendars.ReadWrite.Shared") +
          "&redirect_uri=" + redirectUrl +
          "&state=" + stateParam;
Itay Gal
  • 10,706
  • 6
  • 36
  • 75
  • 1
    Nice work. You can accept your own answer which will help others find this post (questions with accepted answers rank higher in searches) – Phil Jan 16 '19 at 08:46