Skip to content
Skip to main content

Microsoft OAuth scopes for email and calendar

Last updated:

Microsoft deprecated Basic Auth for Exchange Online in October 2022, so every Outlook and Microsoft 365 account now connects through OAuth 2.0 and Microsoft Graph permissions. This page lists the exact Graph scopes Nylas requests for each email, calendar, and contacts feature, so you grant the narrowest set that still works.

For the generic cross-provider scope strings (Google plus Microsoft side by side), see OAuth scopes for email and calendar. This page is the Microsoft-only deep reference.

What Microsoft Graph scopes does Nylas request?

Section titled “What Microsoft Graph scopes does Nylas request?”

Nylas requests Microsoft Graph delegated permissions: short names like Mail.Read with no URI prefix, scoped to the signed-in user rather than the whole tenant. The 7 scopes below cover reading and sending mail, managing calendars and events, and reading contacts. Add offline_access to every set so the access token can refresh.

The table maps each Nylas feature to the Graph scope it needs. These names are verified against the Microsoft tab in the granular scopes reference and the OpenAPI x-scopes, so you can copy them into your Azure app registration without guessing.

FeatureRequired Graph scopeWider scope that also works
Read messages and attachmentsMail.ReadMail.ReadWrite
Update or delete messagesMail.ReadWriteMail.ReadWrite.Shared
Send emailMail.SendNone
Read and write draftsMail.ReadWriteMail.ReadWrite.Shared
Read and write foldersMail.ReadWriteNone
Read calendars and Free/BusyCalendars.ReadCalendars.ReadWrite
Create or update eventsCalendars.ReadWriteNone
Read contactsContacts.ReadPeople.Read
Read and write contactsContacts.ReadWriteNone
Read room and resource calendarsPlace.Read.AllNone

Mail and calendar permissions are separate in Graph, so a calendar-only app never requests a Mail.* scope. Request Mail.ReadWrite and Mail.Send together when you schedule messages for future delivery, which the scopes reference calls out for scheduled send.

Two scopes tie to specific Nylas features rather than to a basic read or write action. Place.Read.All powers GET /v3/grants/<NYLAS_GRANT_ID>/resources, which lists bookable room and equipment resources for meeting scheduling. People.Read is required for the contacts inbox and domain sources, which surface people the user has emailed or who share their tenant directory. Skip both unless your app uses room booking or directory-derived contacts.

Microsoft delegated access tokens expire after about 60 to 90 minutes. offline_access is the Graph scope that returns a long-lived refresh token alongside the access token, and without it the grant stops working after the first token expires with no way to renew. Nylas refreshes the token for you once the scope is granted.

Add offline_access to every scope set, even a read-only one. The hosted OAuth flow at GET /v3/connect/auth sends the connector’s scopes to Microsoft, the user consents once, and the returned refresh token keeps the grant alive until the user or the tenant admin revokes it. Without the refresh token, a background sync job that runs every few hours fails the moment the first 60-minute access token expires, and the grant reports an authentication error until the user reconnects.

The example below shows a read-and-send Microsoft scope set on the authorization request. The four scope names are space-separated in the scope query parameter, exactly as Microsoft expects them.

Delegated vs application permissions in Microsoft Graph

Section titled “Delegated vs application permissions in Microsoft Graph”

Microsoft Graph offers two permission types, and Nylas uses delegated permissions exclusively. Delegated permissions act on behalf of the signed-in user during an interactive OAuth flow, so the grant can only touch data that user can already see. Application permissions act tenant-wide with no user present and always require admin consent before any account connects.

The distinction decides whether a single admin click or per-user consent unblocks your app. Delegated scopes like Mail.Read let an ordinary user consent for their own mailbox on the standard consent screen. In a locked-down Microsoft 365 tenant, an administrator can still gate even delegated scopes behind tenant-wide approval, which is one click that covers every user at once. Application permissions never offer per-user consent, so granting an application-type Mail.Read in Azure and expecting the hosted flow to use it leads to a common dead end.

Plan for admin consent when your target customers run managed tenants. A 2022 Microsoft change tightened default consent settings, so many enterprise tenants now block user consent entirely and route every new app through an admin. Walk admins through the one-time grant with the Microsoft admin approval guide, and point users who hit the consent wall to Fix the need admin approval error.

You need the .Shared scope variants when your app reads or writes a mailbox or calendar that the signed-in user doesn’t own, such as a shared support inbox or a delegate’s calendar. The base Mail.Read scope only covers the user’s own mailbox, so accessing a shared mailbox requires Mail.Read.Shared or Mail.ReadWrite.Shared on top of it.

Microsoft Graph defines 3 shared variants that map to the Nylas features below. Mail.Read.Shared and Mail.ReadWrite.Shared cover delegated mailbox folders, and Calendars.ReadWrite.Shared covers a delegate’s calendar. The scopes reference lists these 3 scopes as “other scopes” for the messages, drafts, folders, and calendar endpoints, so a delegated request still works when the wider shared scope is present.

Shared scenarioGraph scope
Read a shared or delegated mailboxMail.Read.Shared
Write to a shared or delegated mailboxMail.ReadWrite.Shared
Manage a delegate’s calendarCalendars.ReadWrite.Shared

Request a .Shared scope only when the use case demands it. A help-desk app that reads one team inbox needs Mail.Read.Shared, but a personal email client never does, and asking for it inflates the consent screen for no reason. The shared Outlook folders guide covers how Nylas exposes delegated mailbox folders once the scope is granted.

How do I set Microsoft scopes in the Nylas SDKs?

Section titled “How do I set Microsoft scopes in the Nylas SDKs?”

You set Microsoft scopes on the connector or pass them to the SDK’s OAuth URL builder, not on each API call. The urlForOAuth2 method takes your client ID, the microsoft provider, your callback URI, and a scope array of Graph permission names. Generate the URL per user, then redirect them to Microsoft to consent.

The 5 examples below build the same Microsoft authorization URL with a set of 4 scopes: Mail.Read, Mail.Send, Calendars.ReadWrite, and offline_access. Swap the array for ["Calendars.ReadWrite", "offline_access"] for a calendar-only app, or add Contacts.Read when you sync contacts.

Choose the least-privilege Microsoft scope set

Section titled “Choose the least-privilege Microsoft scope set”

Request the smallest scope that covers your features, then widen only when a feature needs it. A smaller consent screen converts better, and a leaked token reaches less data. The table maps 5 common app types to the minimal Microsoft scopes each needs, from a single scope for a read-only inbox up to 4 scopes for a mail-plus-calendar app, with offline_access on every row.

App typeMicrosoft Graph scopes
Read-only inboxMail.Read, offline_access
Full email clientMail.ReadWrite, Mail.Send, offline_access
Calendar schedulerCalendars.ReadWrite, offline_access
Contacts syncContacts.Read, offline_access
Mail plus calendarMail.ReadWrite, Mail.Send, Calendars.ReadWrite, offline_access

Each row maps to a real product shape. A read-only inbox app that classifies or indexes mail needs only Mail.Read plus offline_access, two scopes total, because it never modifies or sends. A full email client that marks messages read, moves them between folders, and sends replies needs Mail.ReadWrite for the modify and folder operations and Mail.Send for outbound mail. A calendar scheduler that creates and updates events needs Calendars.ReadWrite and nothing from the Mail.* family. A one-way contacts sync that only reads the address book needs Contacts.Read, and upgrades to Contacts.ReadWrite only if it writes contacts back.

Don’t request Mail.ReadWrite when your app only reads mail. Unlike Google, Microsoft doesn’t push you into a third-party security assessment for write scopes, but a tenant admin reviewing the consent screen sees every permission you ask for, and an over-broad request is a common reason a connection gets blocked in a locked-down Microsoft 365 tenant. Over-requesting also draws more scrutiny during a tenant’s app review, and any later scope addition forces every connected user back through consent.

Run through this checklist before you finalize a Microsoft scope set:

  1. List the exact Nylas endpoints your app calls, then map each to its required scope in the table above.
  2. Drop any scope no endpoint needs, including .Shared variants unless you read another user’s mailbox.
  3. Use the read scope, not the write scope, wherever your app only reads. Mail.Read over Mail.ReadWrite, Calendars.Read over Calendars.ReadWrite.
  4. Add offline_access so the grant can refresh, since every app needs it.
  5. Add Place.Read.All only for room booking and People.Read only for inbox or domain contact sources.

Beyond the delegated-versus-application split and the .Shared variants covered above, a few more details change how and when these scopes take effect. Each of the 4 items below maps to a real failure mode developers hit during Microsoft integration.

  • Adding a scope forces re-authentication. Microsoft only grants new scopes at consent time. Add Mail.Send after a user already connected with Mail.Read, and their existing grant doesn’t gain it. The user re-authenticates through the flow to pick up the wider access.
  • Conferencing autocreate needs an extra scope. Set up automatic Teams links on events and you also request OnlineMeetings.ReadWrite alongside Calendars.ReadWrite. See enable autocreate for conferencing for the full setup.
  • Contacts sources change the scope. The base Contacts.Read scope covers the user’s personal address book, but the inbox and domain contact sources need People.Read. Request it only when you read directory or recent-correspondent contacts.
  • EWS scopes differ. Exchange Web Services accounts don’t use Graph permission names. Microsoft retired EWS in Exchange Online in 2022, so most accounts should connect with the Graph scopes above instead.

The canonical list lives in the Microsoft Graph permissions reference. Cross-check any scope against it before you add it, because Microsoft renames and deprecates permissions over time.