How to use Exchange Online RBAC and the Graph API to configure application permissions to access mailboxes

Application permissions to access mailboxes

Sometimes you work on an application that needs access all mailboxes in your organization on Exchange Online.

Apps that have been granted the following application permissions

  • Calendars.Read - Allows the app to read events of all calendars without a signed-in user.
  • Calendars.ReadBasic.All - Allows the app to read events of all calendars, except for properties such as body, attachments, and extensions, without a signed-in user.
  • Calendars.ReadWrite - Allows the app to create, read, update, and delete events of all calendars without a signed-in user.
  • Contacts.Read - Allows the app to read all contacts in all mailboxes without a signed-in user.
  • Contacts.ReadWrite - Allows the app to create, read, update, and delete all contacts in all mailboxes without a signed-in user.
  • Mail.Read - Allows the app to read mail in all mailboxes without a signed-in user.
  • Mail.ReadBasic - Allows the app to read basic mail properties in all mailboxes without a signed-in user. Includes all properties except body, previewBody, attachments and any extended properties.
  • Mail.ReadWrite - Allows the app to create, read, update, and delete mail in all mailboxes without a signed-in user. Does not include permission to send mail.
  • Mail.Send - Allows the app to send mail as any user without a signed-in user.
  • MailboxSettings.Read - Allows the app to read user's mailbox settings without a signed-in user. Does not include permission to send mail.
  • MailboxSettings.ReadWrite - Allows the app to create, read, update, and delete user's mailbox settings without a signed-in user. Does not include permission to send mail.

can access all the mailboxes. If you want to limit app access to specific mailboxes, Exchange administrators have to configure Application Access Policy through Exchange Online tools.

You can't do the whole setup with one tool, but you need Microsoft Entra tool like the Graph API (create Entra app, grant application permissions) and Exchange Online tool (limit access to specific mailboxes).

Fortunately, the Graph API comes with a new set of endpoints for Exchange Online RBAC provider to make the process simpler.

Role-Based Access Control (RBAC)

Let's start with basic terms.

Role definition

A role definition (just called a role) is a collection of permissions. A role lists the actions that can be performed.

Security principal

A security principal is an object that represents a user, group, service principal, or managed identity that is requesting access to tenant resources. Role can be assigned to any of these security principals.

Scope

Scope is the set of resources that the access applies to. When you assign a role, you can further limit the actions allowed by defining a scope.

Role assignment

A role assignment is the process of attaching a role definition to a user, group, service principal, or managed identity at a particular scope for the purpose of granting access.

  • Access is granted by creating a role assignment
  • Access is revoked by removing a role assignment

Exchange Online RBAC provider

Exchange Online RBAC provider allows admins to grant permissions to an application that's independently accessing data in Exchange Online. This grant can be paired with a scope of access (resource scope) to specify which mailboxes an app can access. This feature extends the current RBAC model in Exchange Online and it replaces Application Access Policies.

The Graph API beta provides endpoints to list role definitions for Exchange Online RBAC provider and create, remove and list role assignments.

Application roles

Let's explore the roles that are allowed by Exchange Online RBAC provider for service principals. When using the Graph PowerShell SDK, use Get-MgBetaRoleManagementExchangeRoleDefinition cmdlet.

Import-Module Microsoft.Graph.Beta.DeviceManagement.Enrollment

Connect-MgGraph -Scopes "RoleManagement.Read.Exchange"

Get-MgBetaRoleManagementExchangeRoleDefinition -Filter "allowedPrincipalTypes eq 'servicePrincipal'"
Name Id Description Application permissions for Graph API
Application Mail.Read 1f704712-7d46-481f-b2cd-dbcc978c4f2a Allows the app to read email in all mailboxes without a signed-in user Mail.Read
Application Mail.ReadBasic 3eca55c8-0e73-4c12-81bf-526549f2e5a3 Allows the app to read email except the body, previewBody, attachments, and any extended properties in all mailboxes without a signed-in user Mail.ReadBasic
Application Mail.ReadWrite 82fd214e-61ca-4dc7-98f6-090700bdb205 Allows the app to create, read, update, and delete email in all mailboxes without a signed-in user. Does not include permission to send mail Mail.ReadWrite
Application Mail.Send 8679f4ff-c91d-40d0-809c-c86d114821a5 Allows the app to send mail as any user without a signed-in user Mail.Send
Application MailboxSettings.Read c40299e0-2107-455f-85dd-6e8862c3a0cc Allows the app to read user's mailbox settings in all mailboxes without a signed-in user MailboxSettings.Read
Application MailboxSettings.ReadWrite 459cb245-07c5-44f1-8133-3da40b4b6197 Allows the app to create, read, update, and delete user's mailbox settings in all mailboxes without a signed-in user MailboxSettings.ReadWrite
Application Calendars.Read a3123d4e-4256-4ad0-bef0-205a00807fae Allows the app to read events of all calendars without a signed-in user Calendars.Read
Application Calendars.ReadWrite b92761c0-5311-4908-92ca-2c1f8c71aa1c Allows the app to create, read, update, and delete events of all calendars without a signed-in user Calendars.ReadWrite
Application Contacts.Read 9b87c446-d3c1-4146-9d39-45ae63b4eeb7 Allows the app to read all contacts in all mailboxes without a signed-in user Contacts.Read
Application Contacts.ReadWrite 265cabb3-13d9-4e05-b2cd-460cfa7ad3cc Allows the app to create, read, update, and delete all contacts in all mailboxes without a signed-in user Contacts.ReadWrite
Application Mail Full Access b49ae303-7a8f-4ba1-aa37-27b40461aabb Allows the app to create, read, update, and delete email in all mailboxes as well as send mail as any user without a signed-in user Mail.Send Mail.ReadWrite
Application Exchange Full Access 48d6a78c-0681-4d73-acec-9f9ffad56ddb Without a signed-in user: Allows the app to create, read, update, and delete email in all mailboxes as well as send mail as any user. Allows the app to create, read, update, and delete user's mailbox settings in all mailboxes. Allows the app to create, read, update, and delete events of all calendars. Allows the app to create, read, update, and delete all contacts in all mailboxes Contacts.ReadWrite Calendars.ReadWrite MailboxSettings.ReadWrite Mail.Send Mail.ReadWrite

Each role definition includes a list of Graph API role permissions.

Security principal

Only allowed security principal for Exchange Online provider is a service principal (it means also managed identity)

Scope

For Exchange Online provider, the scope for the role assignment can be the whole tenant, a specific user, a specific group (direct members), or an administrative unit.

Check the table below for correct formats

Scope Format
Tenant-wide /
User /Users/{userId}
Administrative unit /AdministrativeUnits/{administrativeUnitId}
Group /Groups/{groupId}

Examples

Example 1

You would like to create an app that can read calendars of users which are members of a administrative unit called Developers.

The steps are:

1. Create an application

Use New-MgBetaApplication cmdlet.

Import-Module Microsoft.Graph.Beta.Applications

$params = @{
	displayName = "CalendarsReader"
}

$app = New-MgBetaApplication -BodyParameter $params
$appObjectId = $app.Id
$appId = $app.AppId

2. Create a service principal

By using New-MgBetaServicePrincipal. It requires application id (appId).

$params = @{
	appId = "$appId"
}

$servicePrincipal = New-MgBetaServicePrincipal -BodyParameter $params
$principalId = $servicePrincipal.Id

3. Add client secret

By using Add-MgBetaApplicationPassword. It requires application object id.

$params = @{
	passwordCredential = @{
		displayName = "Default secret"
	}
}

$appSecret = Add-MgBetaApplicationPassword -ApplicationId $appObjectId -BodyParameter $params
$clientSecret = $appSecret.SecretText

4. Create role assignment

The last step is to create a new role assignment by using New-MgBetaRoleManagementExchangeRoleAssignment. For the assignment, we need service principal id, role definition id and administrative unit id.

Import-Module Microsoft.Graph.Beta.DeviceManagement.Enrollment

$unit = Get-MgBetaAdministrativeUnit -Filter "displayName eq 'Developers'"
$unitId = $unit.Id

$role = Get-MgBetaRoleManagementExchangeRoleDefinition -Filter "displayName eq 'Application Calendars.Read'"
$roleId = $role.Id

$params = @{
	principalId = "/ServicePrincipals/${principalId}"
	roleDefinitionId = $roleId
	directoryScopeId = "/AdministrativeUnits/${unitId}"
	appScopeId = $null
}

New-MgBetaRoleManagementExchangeRoleAssignment -BodyParameter $params

The whole PowerShell script

Import-Module Microsoft.Graph.Beta.Applications
Import-Module Microsoft.Graph.Beta.DeviceManagement.Enrollment

Connect-MgGraph -Scopes "RoleManagement.ReadWrite.Exchange", "Application.ReadWrite.All"

# create app
$params = @{
	displayName = "CalendarsReader"
}

$app = New-MgBetaApplication -BodyParameter $params
$appObjectId = $app.Id
$appId = $app.AppId

# create service principal

$params = @{
	appId = "$appId"
}

$servicePrincipal = New-MgBetaServicePrincipal -BodyParameter $params
$principalId = $servicePrincipal.Id

# wait for a while until service principal is fully provisioned
Start-Sleep 20

# add client secret
$params = @{
	passwordCredential = @{
		displayName = "Default secret"
	}
}

$appSecret = Add-MgBetaApplicationPassword -ApplicationId $appObjectId -BodyParameter $params
$clientSecret = $appSecret.SecretText

# create role assignment

$unit = Get-MgBetaAdministrativeUnit -Filter "displayName eq 'Developers'"
$unitId = $unit.Id

$role = Get-MgBetaRoleManagementExchangeRoleDefinition -Filter "displayName eq 'Application Calendars.Read'"
$roleId = $role.Id

$params = @{
	principalId = "/ServicePrincipals/${principalId}"
	roleDefinitionId = $roleId
	directoryScopeId = "/AdministrativeUnits/${unitId}"
	appScopeId = $null
}

New-MgBetaRoleManagementExchangeRoleAssignment -BodyParameter $params

Test

Use Get-MgBetaUserEvent cmdlet to confirm that the app can access calendars only for users from Developers administrative unit. Read events for one user which is a member of the administrative unit and for user which is not a member.

Import-Module Microsoft.Graph.Beta.Calendar

$tenantId = "<tenant_id>"
$clientSecret = "<client_secret>"
$appId = "<app_id>"
$clientSecretCredential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $appId, (ConvertTo-SecureString -String $clientSecret -AsPlainText -Force)

Connect-MgGraph -ClientSecretCredential $clientSecretCredential -TenantId $tenantId

Write-Host "Reading events for Nestor Wilke"

$events = Get-MgBetaUserEvent -UserId '74db2ae6-6aa4-4160-8c2a-c93d4f1cfafa'

Write-Host "Number of events: " $events.length

Write-Host "Reading events for Adele Vence"

Get-MgBetaUserEvent -UserId '61b0c52f-a902-4769-9a09-c6628335b00a'

Disconnect-MgGraph

As you can see from the result, the attempt to read Adele Vence calendar failed with error code ErrorAccessDenied, because Adele is not a member of the administrative unit and the role Calendars.Read is restricted only to the admin unit.

Example 2

You need an app that will synchronize contacts between users from Sales department. The app will be assigned the Application Contacts.ReadWrite role and restricted to the Sales group.

$group = Get-MgBetaGroup -Filter "displayName eq 'Sales'"
$groupId = $group.Id

$role = Get-MgBetaRoleManagementExchangeRoleDefinition -Filter "displayName eq 'Application Contacts.ReadWrite'"
$roleId = $role.Id

$params = @{
	principalId = "/ServicePrincipals/${principalId}"
	roleDefinitionId = $roleId
	directoryScopeId = "/Groups/${groupId}"
	appScopeId = $null
}

New-MgBetaRoleManagementExchangeRoleAssignment -BodyParameter $params

Example 3

Some company employees are on vacation without access to their emails. You need an app that will check emails from a specific customers. The app will be assigned the Application Mail.ReadBasic role and restricted to a specific user.

$userId = '{user_id}'

$role = Get-MgBetaRoleManagementExchangeRoleDefinition -Filter "displayName eq 'Application Mail.ReadBasic'"
$roleId = $role.Id

$params = @{
	principalId = "/ServicePrincipals/${principalId}"
	roleDefinitionId = "$roleId
	directoryScopeId = "/Users/${userId}"
	appScopeId = $null
}

New-MgBetaRoleManagementExchangeRoleAssignment -BodyParameter $params

Example 4

Your employee is missing, you need an app with the full access to employee's mailbox. The app will be assigned the Application Exchange Full Access role and restricted to a specific user.

$userId = '{user_id}'

$role = Get-MgBetaRoleManagementExchangeRoleDefinition -Filter "displayName eq 'Application Exchange Full Access'"
$roleId = $role.Id

$params = @{
	principalId = "/ServicePrincipals/${principalId}"
	roleDefinitionId = "$roleId
	directoryScopeId = "/Users/${userId}"
	appScopeId = $null
}

New-MgBetaRoleManagementExchangeRoleAssignment -BodyParameter $params

Example 5

You need an app that can change mailbox settings like default time zone, date and time format, track working hours of all users in your tenant. The app will be assigned the Application MailboxSettings.ReadWrite role without any scope restriction.

$role = Get-MgBetaRoleManagementExchangeRoleDefinition -Filter "displayName eq 'Application MailboxSettings.ReadWrite'"
$roleId = $role.Id

$params = @{
	principalId = "/ServicePrincipals/${principalId}"
	roleDefinitionId = "$roleId"
	directoryScopeId = "/"
	appScopeId = $null
}

New-MgBetaRoleManagementExchangeRoleAssignment -BodyParameter $params

Conclusion

Exchange Online RBAC provider offers an alternative way to configure application permissions to access users mailboxes, and can be used side-by-side with granting application permissions and configuring application access policies.

https://learn.microsoft.com/graph/api/rbacapplication-post-roleassignments?view=graph-rest-beta

0
Buy Me a Coffee at ko-fi.com
An error has occurred. This application may no longer respond until reloaded. Reload x