> ## Documentation Index
> Fetch the complete documentation index at: https://support.configview.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Microsoft Dynamics 365 / Dataverse setup

ConfigView reads who can do what in **Dynamics 365** and in every other **Dataverse** environment (the database under Dynamics 365 Sales, Customer Service, Field Service and model-driven Power Apps). It reads each environment's users, security roles, the roles each user and team holds, teams and their members, and business units. It signs in as a **Microsoft Entra app registration (a service principal)**, the same one you may already have set up for the [Azure](https://support.configview.com/azure.md), [Microsoft 365](https://support.configview.com/microsoft-365.md), [Power Platform](https://support.configview.com/power-platform.md) and [Power BI](https://support.configview.com/power-bi.md) integrations, so there is usually **no new credential to create**. What is new is adding that app as an **Application User** in each environment (Step 2).

You will end up with **3 required secrets** in ConfigView: `MSFT_TENANT_ID`, `MSFT_CLIENT_ID` and `MSFT_CLIENT_SECRET_VALUE`, shared with the other Microsoft integrations, and **1 optional secret**, `DATAVERSE_ENVIRONMENT_URLS`.

> **This integration shares the Entra app registration with the other Microsoft integrations.** If any of them is already connected, the three `MSFT_*` secrets are already saved. Rotating the app's client secret affects all of them. Dynamics 365 has its own page and its own tables (`dataverse_*`).

> **What ConfigView reads, and what it never reads.** ConfigView reads user records (name, sign-in name, email, Entra object id, application id, enabled or disabled, access mode, licence type, business unit), security role names and which users and teams hold them, teams with their type and members, and business units. It **never** reads business records (accounts, contacts, opportunities, cases or anything else), role privilege definitions, user addresses, phone numbers or photos. It never creates, changes or deletes anything.

***

## What you need

* A Microsoft Entra app registration (see [Azure setup, Part 1](https://support.configview.com/azure.md) if you do not have one) with a client secret. **Dataverse needs no Entra "API permissions"**: access is granted inside each environment instead (Step 2).
* A person with the **Power Platform Administrator**, Dynamics 365 Administrator or Global Administrator role, or the System Administrator role in each environment, for Step 2.
* For the "disabled in Entra" check: the app should hold **User.Read.All** and **Application.Read.All** (Microsoft Graph, application permissions). Both are already granted if the [Microsoft 365](https://support.configview.com/microsoft-365.md) integration is connected. Without them the integration still works; those columns stay empty.
* Environments in the **commercial cloud**. Sovereign clouds (GCC High, DoD, China) use other sign-in and admin hosts; tell us and we will set `DATAVERSE_LOGIN_BASE` and `DATAVERSE_BAP_BASE` for you.

***

## Step 1: Open the Dynamics 365 page in ConfigView

Open ConfigView in a second browser tab and leave it open:

`https://{companyname}.configview.com/admin/integrations/dynamics-365`

***

## Step 2: Add the app as an Application User in each environment

Dataverse keeps its own list of users in every environment. An app can read an environment only once it is one of those users.

1. Open the [Power Platform admin center](https://admin.powerplatform.microsoft.com) → **Manage → Environments** and select the environment.
2. **Settings → Users + permissions → Application users → + New app user**.
3. **Add an app**: search for the app registration's name or its Application (client) ID and select it.
4. **Business unit**: choose the top (root) business unit, so the app can see the whole environment.
5. **Security roles**: give it a role that can **read** users, security roles, teams and business units across the organization. The least-privilege choice is a copy of Microsoft's **System Reader** role, or a custom role with organization-level Read on *User*, *Security Role*, *Team* and *Business Unit*. Avoid System Administrator: ConfigView only reads, and its own check will list it under "integrations with broad roles" if you give it that.
6. **Create**. Repeat for every environment you want covered.

Microsoft documents this in [Manage application users in the Power Platform admin center](https://learn.microsoft.com/power-platform/admin/manage-application-users).

**Which environments does ConfigView find?** All of them, without you typing a URL, if the app is also registered as a **Power Platform management app** (the [Power Platform](https://support.configview.com/power-platform.md) integration's setup step, `New-PowerAppManagementApp`). ConfigView then lists every environment that has Dataverse. If the app is not a management app, ConfigView falls back to the environments the Power Platform integration last collected. If neither is available, list the environments yourself in `DATAVERSE_ENVIRONMENT_URLS` (Step 3).

Microsoft's Global Discovery Service is not used: it only lists the environments a signed-in person belongs to and does not work for an app.

***

## Step 3: Enter the Entra app in ConfigView

If Azure, Microsoft 365, Power Platform or Power BI is already connected, `MSFT_TENANT_ID`, `MSFT_CLIENT_ID` and `MSFT_CLIENT_SECRET_VALUE` are already filled in. Otherwise paste the **Directory (tenant) ID**, **Application (client) ID** and the client secret **Value** (not the Secret ID).

**Optional: `DATAVERSE_ENVIRONMENT_URLS`.** Leave it empty if environments are found automatically. Otherwise list each **Environment URL** (Power Platform admin center → Environments → the environment → Details), separated by commas or new lines, for example:

```
https://contoso.crm.dynamics.com, https://contoso-uat.crm4.dynamics.com
```

Anything that is not a Dataverse address (a host ending in `dynamics.com`, `microsoftdynamics.us`, `appsplatform.us` or `dynamics.cn`) is ignored. Entries here are added to the environments found automatically.

***

## Step 4: Connect and verify

1. Back on `https://{companyname}.configview.com/admin/integrations/dynamics-365`, confirm the credentials show as saved.
2. Click **Connect**. ConfigView creates its tables and schedules the collector at your default run time:

| Script | Notes |
| - | - |
| **Users, Security Roles, Teams and Business Units (scan)** | Finds the environments, then in each one reads business units, security roles, users, teams, which roles each user and team holds, and team members. Marks users whose Entra account is disabled or deleted. Writes seven tables. |

3. Click **Verify now**. The health check reads the secrets, finds the environments, signs in to up to five of them and calls `WhoAmI`, and checks it can read the Entra user list.

If a check fails:

* **Environment discovery fails.** No environment was found: register the app as a Power Platform management app, connect the Power Platform integration, or fill in `DATAVERSE_ENVIRONMENT_URLS`.
* **Dataverse Web API fails or warns with HTTP 401 or 403** ("The user is not a member of the organization"). The app is not an Application User in that environment yet (Step 2), or its user is disabled there.
* **Microsoft Graph users warns.** Grant `User.Read.All`. Everything else still works.

Environments the app cannot read are not an error: each run records them in `dataverse_environments` with status `not_application_user`, and the catalog query **Dynamics 365 / Dataverse environments ConfigView reads** lists them.

***

## Data Tables

Once the scan runs, these tables are created in your database. Each has `environment_host`, `environment_name` and `run_at` columns and keeps only the newest run.

| Table | Source (Dataverse Web API v9.2) | Key Columns |
| - | - | - |
| `dataverse_environments` | Power Platform admin API + `WhoAmI` | environment\_host, environment\_type, source, status (ok / partial / not\_application\_user / token\_refused), user\_count, enabled\_user\_count, application\_user\_count |
| `dataverse_users` | `systemusers` + Microsoft Graph | systemuser\_id, full\_name, domain\_name, email, entra\_object\_id, application\_id, is\_application\_user, is\_microsoft\_app, is\_this\_app, is\_disabled, access\_mode\_label, is\_licensed, azure\_state\_label, entra\_status (enabled / disabled / not\_found) |
| `dataverse_roles` | `roles` | name, business\_unit\_name, root\_role\_id, role\_template\_id, is\_system\_administrator, is\_broad, user\_holders, team\_holders |
| `dataverse_role_assignments` | `systemuserrolescollection`, `teamrolescollection` | principal\_type (user / team), principal\_name, role\_name, is\_system\_administrator, is\_broad |
| `dataverse_teams` | `teams` | name, team\_type\_label (Owner / Access / Entra security group / Microsoft 365 group), business\_unit\_name, member\_count, role\_count |
| `dataverse_team_members` | `teammembershipcollection` | team\_name, systemuser\_id, user\_name, user\_domain\_name |
| `dataverse_business_units` | `businessunits` | name, parent\_name, is\_root, is\_disabled, user\_count |

`is_system_administrator` is 1 for Microsoft's **System Administrator** role (template `627090ff-40a3-4053-8790-584edc5be201`, or the name). `is_broad` also covers **System Customizer**. Dataverse copies every role into each business unit; `root_role_id` ties the copies together.

***

## Things worth knowing

**Effective roles include teams.** A user gets the roles assigned to them and the roles of every Dataverse team they are in. The catalog checks count both and say which team a role came from. Teams backed by an Entra group only list members who have signed in to that environment at least once, so access through those teams can be understated.

**Disabled in Entra, still enabled in Dataverse.** Dataverse normally disables a user soon after their Entra account is disabled or deleted. ConfigView reads each user's Entra state directly from Microsoft Graph and also Dataverse's own `azurestate` (Exists / Soft deleted / Not found), so a sync that did not happen shows up as a finding.

**Application users.** An application user is an app or integration signing in with its own secret or certificate. ConfigView asks Microsoft Graph which organization published each one: Microsoft's own built-in application users (for search, portals, Copilot and similar) are left out of the risk checks, ConfigView's own app user is labelled, and apps registered in another organization are marked third-party.

**Microsoft's limits.** Dataverse allows 6,000 requests per 5 minutes per user (here the application user). A scan costs about 9 calls per environment plus one per 5,000 records, runs one call at a time at no more than 120 a minute, and stops after 25 minutes or 200 environments, keeping what it read and mailing a partial-run notice.

**First-tenant checks.** This integration was built from Microsoft's documentation without a live Dynamics 365 tenant. After the first run, check that `dataverse_role_assignments` has rows (if an environment refuses the intersect tables ConfigView falls back to reading each user's roles) and that `entra_status` is filled in for people.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.