401 Unauthorized Error When Fetching Calendar Events via Microsoft Graph API Despite Correct Permissions

Suleman Dar 0 Reputation points
2025-10-24T13:17:20.6666667+00:00

๐ŸŸฆ Title

401 Unauthorized when calling Microsoft Graph Calendar API (App-only flow) even with correct permissions in token


๐ŸŸฉ Body

Iโ€™m trying to fetch calendar events using the App-only (client credentials) flow with Microsoft Graph API. The token is issued successfully, but every request to /users/{id}/calendar/events or /users/{id}/events returns 401 Unauthorized.


๐Ÿ”น Token details (decoded via jwt.ms)

{
  "aud": "https://graph.microsoft.com",
  "iss": "https://sts.windows.net/950a4376-c358-4553-980a-9ba773e48dff/",
  "iat": 1761310165,
  "nbf": 1761310165,
  "exp": 1761314065,
  "aio": "k2JgYIg/4yn16NcS5/v1616vPJgaDQA=",
  "app_displayname": "Multi tenant app",
  "appid": "1409b9f1-217e-49ad-8180-898d1e0dfddf",
  "appidacr": "1",
  "idtyp": "app",
  "roles": [
    "User.ReadBasic.All",
    "User.ReadWrite.All",
    "Application.ReadWrite.OwnedBy",
    "Calendars.Read",
    "Application.ReadWrite.All",
    "Application.ReadUpdate.All",
    "User.Read.All",
    "Calendars.ReadBasic.All",
    "Calendars.ReadWrite",
    "Application.Read.All"
  ],
  "tid": "950a4376-c358-4553-980a-9ba773e48dff",
  "ver": "1.0"
}

๐Ÿ”น Request Example

GET https://graph.microsoft.com/v1.0/users/{user_id}/calendar/events
Authorization: Bearer {access_token}
Content-Type: application/json

Response:

{
  "error": {
    "code": "InvalidAuthenticationToken",
    "message": "Access token validation failure. Invalid audience or permissions."
  }
}

๐Ÿ”น What Iโ€™ve Verified

โœ… Token audience (aud) = https://graph.microsoft.com โœ… Token contains Calendars.ReadWrite and User.Read.All roles โœ… Admin consent granted in Azure Portal โœ… Token issued via client credentials flow:

POST https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token
grant_type=client_credentials
client_id={client_id}
client_secret={client_secret}
scope=https://graph.microsoft.com/.default

โœ… App is multi-tenant and consented for Application permissions


๐Ÿ”น The Problem

Despite the correct roles and consent, every request to read or write calendar data results in:

401 Unauthorized
InvalidAuthenticationToken

๐Ÿ”น Questions

Is there any additional Exchange Online or M365 mailbox configuration needed for App-only access to calendars?

Are there differences between delegated (Calendars.ReadWrite) and application (Calendars.ReadWrite) permissions that could cause this?

How can I verify that the service principal has mailbox access for the target user?

Does app-only access require Exchange Online full mailbox delegation for each user?


๐Ÿงฉ Environment

Flow: App-only (client credentials)

API version: v1.0

Tenant ID: 950a4376-c358-4553-980a-9ba773e48dff

App ID: 1409b9f1-217e-49ad-8180-898d1e0dfddf

Graph permissions (Application): Calendars.Read, Calendars.ReadWrite, User.Read.All, User.ReadWrite.All


๐ŸŸจ Goal

Fetch and sync calendar events for organization users using App-only flow (no user login). Looking for clarification why this fails with 401 even though the token includes valid Calendars.ReadWrite roles and audience is correct.

๐ŸŸฆ Title

401 Unauthorized when calling Microsoft Graph Calendar API (App-only flow) even with correct permissions in token


๐ŸŸฉ Body

Iโ€™m trying to fetch calendar events using the App-only (client credentials) flow with Microsoft Graph API.
The token is issued successfully, but every request to /users/{id}/calendar/events or /users/{id}/events returns 401 Unauthorized.


๐Ÿ”น Token details (decoded via jwt.ms)

{

๐Ÿ”น Request Example

GET https://graph.microsoft.com/v1.0/users/{user_id}/calendar/events
Authorization: Bearer {access_token}
Content-Type: application/json

Response:

{

๐Ÿ”น What Iโ€™ve Verified

โœ… Token audience (aud) = https://graph.microsoft.com
โœ… Token contains Calendars.ReadWrite and User.Read.All roles
โœ… Admin consent granted in Azure Portal
โœ… Token issued via client credentials flow:

POST https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token
grant_type=client_credentials
client_id={client_id}
client_secret={client_secret}
scope=https://graph.microsoft.com/.default

โœ… App is multi-tenant and consented for Application permissions


๐Ÿ”น The Problem

Despite the correct roles and consent, every request to read or write calendar data results in:

401 Unauthorized
InvalidAuthenticationToken

๐Ÿ”น Questions

Is there any additional Exchange Online or M365 mailbox configuration needed for App-only access to calendars?

Are there differences between delegated (Calendars.ReadWrite) and application (Calendars.ReadWrite) permissions that could cause this?

How can I verify that the service principal has mailbox access for the target user?

Does app-only access require Exchange Online full mailbox delegation for each user?


๐Ÿงฉ Environment

Flow: App-only (client credentials)

API version: v1.0

Tenant ID: 950a4376-c358-4553-980a-9ba773e48dff

App ID: 1409b9f1-217e-49ad-8180-898d1e0dfddf

Graph permissions (Application):
Calendars.Read, Calendars.ReadWrite, User.Read.All, User.ReadWrite.All


๐ŸŸจ Goal

Fetch and sync calendar events for organization users using App-only flow (no user login).
Looking for clarification why this fails with 401 even though the token includes valid Calendars.ReadWrite roles and audience is correct.

Azure API Management
Azure API Management
An Azure service that provides a hybrid, multi-cloud management platform for APIs.
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. islam kobtan 0 Reputation points
    2025-10-24T23:26:04.2233333+00:00

    Hello Suleman,

    This looks like a classic issue. Your token seems perfect, but the 401 might be coming from Exchange Online itself, not Entra ID.

    Even with the correct Calendars.ReadWrite application roles in the token, Exchange Online often blocks app-only access to mailboxes by default.

    Have you tried setting up an Application Access Policy in Exchange Online?

    This is a separate step in PowerShell (using Connect-ExchangeOnline) that explicitly tells Exchange to trust your App ID (1409b9f1...) and allow it to access a specific scope of mailboxes.

    I wonder if running New-ApplicationAccessPolicy -AppId "1409b9f1-217e-49ad-8180-898d1e0dfddf" -PolicyScopeGroupId "AllUsers" -AccessRight RestrictAccess (or using a specific security group instead of AllUsers) might be the missing piece?

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.