I am trying to book an event in Outlook calendar through Graph API. I have created the application and granted the permission as shown in the screenshot.
The application has both Delegated permission and Application permission
Here is the code that I am using.
import axios from 'axios';
import querystring from 'querystring';
const tenantId = '123456'; // Your Directory (Tenant) ID
const clientId = '-558d64288141'; // Your Application (Client) ID
const clientSecret = 'ZXc8Q~t'; // Your Application Secret Value
async function getAccessToken() {
const tokenEndpoint = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`;
const params = {
grant_type: 'client_credentials',
client_id: clientId,
client_secret: clientSecret,
scope: 'https://graph.microsoft.com/.default'
};
const response = await axios.post(tokenEndpoint, querystring.stringify(params), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
return response.data.access_token;
}
async function bookCalendarEvent(accessToken, eventDetails) {
const endpoint = 'https://graph.microsoft.com/v1.0/users/[email protected]/events'; // Updated endpoint
const response = await axios.post(endpoint, eventDetails, {
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
});
return response.data;
}
export const handler = async (event) => {
try {
// Get access token using client credentials
const accessToken = await getAccessToken();
// Sample event details
const eventDetails = {
subject: 'Meeting with Lambda',
body: {
contentType: 'HTML',
content: 'This is a meeting scheduled by AWS Lambda'
},
start: {
dateTime: '2024-08-27T09:00:00', // Sample start date and time
timeZone: 'UTC'
},
end: {
dateTime: '2024-08-27T10:00:00', // Sample end date and time
timeZone: 'UTC'
},
attendees: [
{
emailAddress: {
address: '[email protected]', // Sample attendee email
name: 'John Doe'
},
type: 'required'
}
]
};
// Book the calendar event
const result = await bookCalendarEvent(accessToken, eventDetails);
return {
statusCode: 200,
body: JSON.stringify({
message: 'Event booked successfully',
eventId: result.id
})
};
} catch (error) {
console.error('Error booking calendar event:', error);
return {
statusCode: 500,
body: JSON.stringify({
message: 'Error booking event',
error: error.message
})
};
}
};
But when I run the AWS Lambda I get this error
{
"statusCode": 500,
"body": "{"message":"Error booking event","error":"Request failed with status code 403"}"
}
So I am not sure what I am doing wrong
Any help
thanks
2
Answers
Since you are using client credentials flow, only application permissions will work. Delegated permissions only work if a user is involved in the token acquisition; which they are not in this case.
For the application permission to work, an app role assignment needs to be granted to the service principal of your app. Pressing the Grant admin consent button will do this (and also add the necessary objects for all the other required permissions you have). You (or someone else) needs to have Application Admin / Cloud Application Admin / Global Admin role.
I agree with @juunas, you need to switch to delegated flows like authorization code flow to have access to only signed-in user’s calendar.
I registered one Azure AD application and granted
Calendars.ReadWrite
permission of Delegated type as below:Now, I added redirect URI as http://localhost:3000/callback in
Web
platform of application like this:In my case, I used below modified code that works with authorization code flow to acquire token and books event in signed-in user calendar:
index.js:
Now, run the code and visit http://localhost:3000/login in browser that asks user to login and gives
code
in address bar after completing authentication like this:When I ran http://localhost:3000/book-event in browser, it booked the event in signed-in user’s calendar successfully like this:
If you try to book event in different user’s calendar, it will give 403 error as access will be denied for users other than signed-in user like this: