Understanding Online Meetings Read Write All: How to Access Teams Meetings Without Exposing Mail or Calendar Data

Many organizations want to build applications that can read or manage Microsoft Teams meetings without exposing sensitive mailbox or calendar data. A common question is whether granting OnlineMeetings.ReadWrite.All (application permission) in Entra ID gives an app access to user emails or calendar event bodies. The short answer is: No, it does not.

This post walks through a real-world test scenario, explains how Teams and Exchange permissions differ, and shows how to safely authorize an app to read Teams OnlineMeeting objects while keeping mailbox content fully protected.

I used Microsoft Copilot AI to assist me with technical guidance. Not everything worked as Copilot initially suggested, but I was able to ask follow up questions as I was navigating the issues during configurations/testing. I used Postman to conduct the testing. At the end of all the conversations, I asked Copilot to write a blog post based on the conversations in the context and it did very nicely! Gen AI (Copilot) makes me (and you) more productive than ever before. Copilot makes mistake and sometimes it is because it does not have the right context (or questions), it is our job to validate the answers/responses. In my case, I used my lab tenant to validate the answers.

Teams Online Meetings vs Outlook Calendar Events

When a user creates a meeting in Outlook and adds a Teams link, two separate objects are created:

  • Outlook Calendar Event (Exchange Online) Contains subject, body, attachments, notes, and all mailbox content.
  • Teams OnlineMeeting Object (Teams Cloud Communications) Contains join URL, meeting options, organizer, start/end time, and metadata.

These two objects look related, but they live in different systems. The OnlineMeetings API only touches the Teams object, not the Outlook calendar event.

What OnlineMeetings.ReadWrite.All Can Do

This permission allows an app to:

  • Read Teams online meeting metadata
  • Create or update Teams meetings
  • Access meeting options (lobby settings, presenters, chat settings, etc.)

It cannot access:

  • Emails
  • Mailbox folders
  • Calendar events
  • Calendar event bodies
  • Attachments
  • Teams chat messages
  • Files or SharePoint content

This separation is intentional and enforced by Microsoft Graph.

Why You Need a Teams Application Access Policy

Even with OnlineMeetings.ReadWrite.All granted, Teams will not allow app-only access until you explicitly authorize the app using a Teams Application Access Policy. This is a Teams-specific authorization mechanism and is completely separate from Exchange RBAC.

Without this policy, Graph returns:

No application access policy found for this app on the user

To authorize the app for all users, assign the policy to the global scope: Here is sample logical code and sample code-

New-CsApplicationAccessPolicy -Identity OnlineMeetingsTestPolicy -AppIds "<your-app-id>"
Grant-CsApplicationAccessPolicy -PolicyName OnlineMeetingsTestPolicy -Global
# Install module (if needed)
Install-Module MicrosoftTeams

# Connect to Teams
Connect-MicrosoftTeams

# Create the policy
New-CsApplicationAccessPolicy -Identity OnlineMeetingsTestPolicy -AppIds "4a8f9bfc-d8bc-46ad-9de3-0ed0d0f5323e"

# Assign it to the Global scope
Grant-CsApplicationAccessPolicy -PolicyName OnlineMeetingsTestPolicy -Global

# Assign it to the group scope to limit the app data boundary
# Grant-CsApplicationAccessPolicy -PolicyName OnlineMeetingsTestPolicy -Group "Graph-Demo@aspnet4you2.onmicrosoft.com"

This enables the app to read Teams OnlineMeeting objects for every user in the tenant.

Reading a Teams Online Meeting Using Microsoft Graph

Once the policy is applied, you can query a meeting using the joinWebUrl. For example:Code

GET https://graph.microsoft.com/v1.0/users/<user-object-id>/onlineMeetings?$filter=joinWebUrl eq 'https://teams.microsoft.com/meet/replace-your-meeting-id-here?p=qFL6TTk4mdXTDQ9u1W'

Sample response:

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('26846880-50de-4a3a-8dc1-4bc40a62c7f6')/onlineMeetings",
    "value": [
        {
            "creationDateTime": "2026-07-20T02:59:22.4689156Z",
            "startDateTime": "2026-07-20T13:30:00Z",
            "endDateTime": "2026-07-20T14:00:00Z",
            "joinUrl": "https://teams.microsoft.com/l/meetup-join/{truncated}",
            "meetingCode": "262361219403000",
            "isBroadcast": false,
            "autoAdmittedUsers": "everyoneInCompany",
            "joinWebUrl": "https://teams.microsoft.com/l/meetup-join/{truncated}",
            "subject": "Online Meetings Test",
            "meetingType": "scheduled",
            "isEntryExitAnnounced": true,
            "isEndToEndEncryptionEnabled": false,
            "allowedPresenters": "everyone",
            "allowAttendeeToEnableMic": true,
            "allowAttendeeToEnableCamera": true,
            "allowMeetingChat": "enabled",
            "allowedLobbyAdmitters": "organizerAndCoOrganizersAndPresenters",
            "shareMeetingChatHistoryDefault": "none",
            "allowTeamworkReactions": true,
            "anonymizeIdentityForRoles": [],
            "recordAutomatically": false,
            "allowParticipantsToChangeName": false,
            "allowTranscription": true,
            "allowRecording": true,
            "allowWhiteboard": true,
            "allowBreakoutRooms": true,
            "allowLiveShare": "enabled",
            "allowPowerPointSharing": true,
            "allowCopyingAndSharingMeetingContent": true,
            "meetingOptionsWebUrl": "https://teams.microsoft.com/meetingOptions/?organizerId={truncated}",
            "iCalUid": "{truncated}",
            "expiryDateTime": "2026-09-18T14:00:00Z",
            "cloudVideoInteropInfo": {},
            "id": "{truncated}",
            "participants": {
                "organizer": {
                    "upn": "Paul.Smith@aspnet4you2.onmicrosoft.com",
                    "role": "presenter",
                    "identity": {
                        "user": {
                            "@odata.type": "#microsoft.graph.communicationsUserIdentity",
                            "id": "26846880-50de-4a3a-8dc1-4bc40a62c7f6",
                            "tenantId": "c33386cf-6e11-484c-a983-b49975ce571a"
                        }
                    }
                },
                "attendees": [
                    {
                        "upn": "Bob.Smith@aspnet4you2.onmicrosoft.com",
                        "role": "attendee",
                        "identity": {
                            "user": {
                                "@odata.type": "#microsoft.graph.communicationsUserIdentity",
                                "id": "24e66b3d-33a7-4639-9dbc-f1d61883c9d4",
                                "tenantId": "c33386cf-6e11-484c-a983-b49975ce571a"
                            }
                        }
                    }
                ]
            },
            "chatInfo": {
                "threadId": "19:meeting_OWRlZTM5ZGQtMDc4Yy00ZGUwLWE2YzUtYmE0OTcyZDVlY2Y2@thread.v2",
                "messageId": "0"
            },
            "joinInformation": {
                "content": "data:text/html,%3cdiv+style{truncated}",
                "contentType": "html"
            },
            "joinMeetingIdSettings": {
                "isPasscodeRequired": true,
                "joinMeetingId": "{truncated}",
                "passcode": "{truncated}"
            },
            "lobbyBypassSettings": {
                "scope": "organization",
                "isDialInBypassEnabled": false
            }
        }
    ]
}

If Teams created an OnlineMeeting object, Graph returns full metadata including:

  • subject
  • startDateTime / endDateTime
  • organizer and attendees
  • meetingCode and passcode
  • meetingOptionsWebUrl
  • allowedPresenters
  • chatInfo
  • joinMeetingIdSettings

This confirms the app can read Teams meeting metadata safely.

Testing Mailbox Access: Why It Fails (And Why That’s Good)

Using the same access token, we attempted to read email:Code

GET https://graph.microsoft.com/v1.0/users/Paul.Smith@aspnet4you2.onmicrosoft.com/messages

Graph returned:

ErrorAccessDenied

This proves:

  • The app has no Exchange Online permissions
  • OnlineMeetings.ReadWrite.All does not grant mailbox access
  • Teams Application Access Policies do not affect email or calendar
  • Exchange RBAC protections remain fully intact

This is exactly the isolation most organizations want.

Final Summary

By combining:

  • OnlineMeetings.ReadWrite.All (Teams permission)
  • Teams Application Access Policy (Global scope)

You can safely allow an app to read Teams OnlineMeeting objects for all users without exposing:

  • emails
  • calendar bodies
  • attachments
  • mailbox folders

This architecture provides strong separation between Teams meeting metadata and Exchange mailbox content, enabling secure meeting governance, compliance, and automation scenarios.

Leave a Reply