MSP Documentation
How to configure Microsoft 365
Create a Microsoft 365 app registration that Dex can use to manage a customer tenant. About 3 minutes with the automated PowerShell script, or 5–10 minutes manually — requires Global Administrator on the customer's tenant.
Overview
This guide walks you through creating a Microsoft 365 app registration that Dex can use to manage a customer tenant. At the end you will have three values to paste into the Add tenant dialog:
- Directory (tenant) ID
- Application (client) ID
- Client secret value
The automated script takes about 3 minutes; the manual route 5–10 minutes. Either way, it must be performed by someone with Global Administrator (or Privileged Role Administrator + Cloud Application Administrator) on the customer's Microsoft 365 tenant.
App-only integration
Dex uses an application (app-only) integration — not a delegated user login. This means Dex can act on the tenant even when no user is signed in, which is required for autonomous remediation and scheduled discovery.
Choose how you want to set it up
Both paths end at the same place: three values to paste into the Dex Add tenant dialog. The guide below shows only the path you pick.
Run the setup script
Instead of clicking through the Entra portal, run one script that creates the app registration, the client secret, all required Microsoft Graph permissions, and grants admin consent — then prints the three values you need for the Dex Add tenant dialog. Takes about 3 minutes per tenant and requires a Global Administrator account on the customer's tenant.
Download: https://download.dex365.ai/windows/Setup-DexTenant.ps1
Option A — Azure Cloud Shell (nothing to install)
Cloud Shell runs in the browser with the Microsoft Graph modules already available, so this works the same on any computer.
- Open a private/incognito window (so you don't mix up tenants) and go to https://shell.azure.com.
- Sign in with a Global Administrator account of the customer's tenant. If prompted, choose PowerShell (not Bash) and No storage account required if offered.
- Paste these two lines and press Enter:
Invoke-WebRequest -Uri "https://download.dex365.ai/windows/Setup-DexTenant.ps1" -OutFile Setup-DexTenant.ps1
./Setup-DexTenant.ps1- When prompted, sign in with the same Global Admin account and accept the requested permissions (
Application.ReadWrite.All,AppRoleAssignment.ReadWrite.All). This consent is for running the script, not for Dex itself. - When the script finishes, copy the three printed values — Tenant ID, Client ID, and Client Secret — and continue to Add the tenant in Dex below.
Copy the client secret now
It is shown only once and cannot be retrieved later. If you lose it, re-run the script or create a new secret in Entra.
Option B — Local PowerShell (Windows, macOS, or Linux)
PowerShell 7+ recommended (Windows PowerShell 5.1 also works). The script auto-installs the Microsoft.Graph.Authentication and Microsoft.Graph.Applications modules to your user profile if missing. No admin rights are needed on the computer — only on the tenant.
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
Invoke-WebRequest -Uri "https://download.dex365.ai/windows/Setup-DexTenant.ps1" -OutFile Setup-DexTenant.ps1
./Setup-DexTenant.ps1Sign in with a Global Administrator of the customer's tenant when the browser prompt appears, then copy the three printed values into the Dex Add tenant dialog.
Managing multiple tenants from one machine? Force the right tenant explicitly:
./Setup-DexTenant.ps1 -TenantId "customer-tenant-id-or-domain.onmicrosoft.com"Optional parameters
| Parameter | Default | Description |
|---|---|---|
-AppName | Dex | Display name of the app registration in Entra. |
-SecretMonths | 24 | Client secret lifetime in months. |
-TenantId | (interactive) | Force sign-in to a specific tenant — useful for MSPs with many tenants. |
What the script does
- Signs in to Microsoft Graph as you (Global Admin), requesting only
Application.ReadWrite.AllandAppRoleAssignment.ReadWrite.Allfor the session. - Creates a single-tenant app registration named Dex.
- Creates a client secret (24 months by default).
- Adds all 27 Microsoft Graph application permissions required by Dex (full list below).
- Creates the service principal (Enterprise Application).
- Grants admin consent for every permission.
- Prints the Tenant ID, Client ID, and Client Secret and disconnects.
The script makes no other changes to the tenant and stores nothing. Once it finishes, continue to Add the tenant in Dex below.
Add the tenant in Dex
- In the Dex MSP dashboard, click Add tenant.
- Enter an Organization name (this is the label that will show in your MSP dashboard — it does not need to match the M365 tenant name).
- Select Microsoft 365.
- Paste the three values you collected:
- Tenant ID → printed by the script
- Client ID → printed by the script
- Client Secret → printed by the script (shown only once)
- Click Add Tenant.
Dex will:
Acquire an app-only token to verify the credentials are valid.
Call /organization on Microsoft Graph to confirm the tenant matches.
Look up the service principal and list its granted app roles.
Compare granted roles against the required list and report any missing ones.
If everything succeeds, the tenant appears in your MSP dashboard and Dex automatically starts a discovery scan.
Permissions the script granted
For reference — these are the 27 Microsoft Graph application permissions Setup-DexTenant.ps1 added and consented to, and why Dex needs each one.
Core identity & directory
| Permission | Why Dex needs it |
|---|---|
User.ReadWrite.All | Create, update, disable, and delete users; reset passwords; manage licenses. |
Directory.ReadWrite.All | Read and write directory objects (users, groups, devices) for org-wide operations. |
Group.ReadWrite.All | Create and manage Microsoft 365 groups, security groups, and distribution lists. |
GroupMember.ReadWrite.All | Add and remove members from groups. |
UserAuthenticationMethod.ReadWrite.All | Manage MFA methods, register/reset authentication methods. |
Audit & security
| Permission | Why Dex needs it |
|---|---|
AuditLog.Read.All | Read sign-in and audit logs for incident investigation. |
Application.Read.All | Read app registrations and service principals during discovery. |
RoleManagement.Read.Directory | Read directory role assignments to evaluate privilege. |
BitlockerKey.Read.All | Retrieve BitLocker recovery keys for device recovery workflows. |
Intune / device management
| Permission | Why Dex needs it |
|---|---|
DeviceManagementApps.ReadWrite.All | Manage Intune app deployments. |
DeviceManagementConfiguration.Read.All | Read Intune configuration and compliance policies. |
DeviceManagementManagedDevices.PrivilegedOperations.All | Wipe, retire, remote lock, and reset managed devices. |
DeviceManagementManagedDevices.ReadWrite.All | Read and update managed device records. |
Exchange / mail
| Permission | Why Dex needs it |
|---|---|
Mail.Send | Send notification and remediation emails from user mailboxes. |
Mail.ReadWrite | Read and modify mailbox contents during investigation and cleanup. |
Calendars.ReadWrite | Manage calendar events during onboarding/offboarding. |
MailboxSettings.ReadWrite | Configure mailbox settings (forwarding, OOO, delegates). |
SharePoint / files
| Permission | Why Dex needs it |
|---|---|
Sites.Read.All | Read SharePoint site metadata for discovery. |
Sites.ReadWrite.All | Manage SharePoint sites and lists. |
Sites.FullControl.All | Required for site provisioning and permission management. |
Files.Read.All | Read OneDrive / SharePoint files for investigation. |
Files.ReadWrite.All | Manage files during offboarding and content cleanup. |
Reports & organization
| Permission | Why Dex needs it |
|---|---|
Organization.Read.All | Read tenant info (display name, verified domains, licenses). |
Reports.Read.All | Pull usage and activity reports for posture analysis. |
ReportSettings.ReadWrite.All | Enable de-anonymized reports so user-level usage data is available. |
Teams
| Permission | Why Dex needs it |
|---|---|
TeamsAppInstallation.ReadWriteForUser.All | Install the Dex Teams app for end users. |
AppCatalog.ReadWrite.All | Upload and update the Dex Teams app in the tenant app catalog. |
Troubleshooting
INVALID_CREDENTIALS
- Double-check you pasted the Tenant ID (not the tenant domain like
contoso.onmicrosoft.com). - Confirm the Client Secret is the Value, not the Secret ID.
- Confirm the secret has not expired. Go to Certificates & secrets in Entra and check the Expires column.
MISSING_PERMISSIONS
- The error response includes the exact list of missing permissions. Go back to API permissions in the app registration, add the missing ones, and click Grant admin consent again. Then retry Add Tenant.
SERVICE_PRINCIPAL_NOT_FOUND
- The app registration exists but no service principal (Enterprise Application) has been created in the tenant yet. This usually means admin consent has never been granted. Click Grant admin consent for <tenant> under API permissions — that step creates the service principal as a side effect.
TENANT_ALREADY_BOUND
- This M365 tenant is already linked to another Dex organization. Contact your Dex administrator.
Script: Insufficient privileges
- The account you signed in with while running
Setup-DexTenant.ps1is not a Global Administrator of this tenant. Sign in with a GA account and re-run the script.
Script: an app named Dex already exists
- The script automatically uses the next free name (Dex 2, Dex 3, …) and prints which name it used. You can delete stale Dex apps later in Entra → App registrations.
Script: some permissions show as failed
- Usually a replication delay. Open Entra → App registrations → Dex → API permissions, click Grant admin consent, then add the tenant in Dex.
- If Dex still returns
MISSING_PERMISSIONS, wait 1–2 minutes (consent propagation) and click Add Tenant again.
Rotating the secret later
Client secrets expire. To rotate without downtime:
- In the app's Certificates & secrets page, create a new client secret.
- In the Dex MSP dashboard, open the tenant and update its credentials with the new secret Value.
- Once Dex confirms the new secret works, delete the old secret in Entra.
Or create the new secret from PowerShell in the customer tenant (then continue from step 2 above):
Connect-MgGraph -Scopes "Application.ReadWrite.All" -NoWelcome
$app = Get-MgApplication -Filter "displayName eq 'Dex'"
$new = Add-MgApplicationPassword -ApplicationId $app.Id -PasswordCredential @{
DisplayName = "Dex integration (rotated)"
EndDateTime = (Get-Date).AddMonths(24)
}
$new.SecretTextSummary checklist
- Ran
Setup-DexTenant.ps1as a Global Administrator of the customer's tenant (Cloud Shell or local PowerShell). - The script finished with admin consent granted for all 27 permissions.
- Copied the three printed values: Tenant ID, Client ID, and Client Secret.
- Pasted the three values into Dex Add tenant and clicked Add Tenant.