Dataverse Connection Setup
Your portal talks to Dataverse as an application in its own right, not as the visitor who happens to be browsing it. That takes two pieces: an app registration in Microsoft Entra ID that owns the credentials, and an application user in your Dataverse environment that gives those credentials a identity and a security role. This page walks through both, and through the access the portal actually needs.
This is not the sign-in app
This registration is the portal's own service identity — it reads and writes data on the portal's behalf, and its credentials go under
D365:ClientId/D365:ClientSecret. A second, separate registration handles signing users in with Microsoft. Keep them apart: this one needs no redirect URI and no delegated permissions, but it holds far more power inside your environment. See Entra ID Sign-In Setup
1. Register the Application
Create the registration in the Microsoft Entra admin center, in the tenant that owns your Dataverse environment.
- Browse to Entra ID > App registrations and select New registration.
- Enter a Name that identifies the portal and the environment, for example
Contoso Portal — Dataverse (Production). Nobody sees this on a consent screen, so favour clarity for whoever audits it later. - Under Supported account types, choose Single tenant only. This identity never leaves your organization.
- Leave Redirect URI empty. No user is ever redirected here — the portal authenticates with the client credentials flow, machine to machine, with no browser involved.
- Select Register.
- On the Overview page, copy the Application (client) ID. That value becomes
D365:ClientId, and you need it again in step 4 to create the application user.
2. Create a Client Secret
The secret is the portal's only credential, so treat it as the key to your environment's data.
- Open Certificates & secrets under Manage and select the Client secrets tab.
- Select New client secret, describe it by environment (for example
portal-production), and choose an expiry. - Copy the Value column immediately — not the Secret ID. It is shown only once, and it becomes
D365:ClientSecret.
Important
When the secret expires the portal stops reaching Dataverse entirely — not just for one feature, but for every request — so put the expiry date somewhere you will see it. For production, a certificate credential avoids the expiry cliff, and
AuthenticationType.Certificateaccepts one in place of the secret.
3. API Permissions: None Required
This step is deliberately empty, and that surprises people. Plenty of older guidance tells you to add the Dynamics CRM → user_impersonation delegated permission. That permission is for applications acting on behalf of a signed-in user. The portal does not do that — it authenticates as itself, and its access comes entirely from the Dataverse application user you create in the next step.
Note
Microsoft's own server-to-server guidance says the same: when you connect as an app, you don't grant Access Dynamics 365 as organization users, because the application is bound to a specific user account instead. Adding it does not break anything, but it grants a capability the portal never exercises — leave it off.
4. Create the Application User in Dataverse
The app registration alone cannot touch data. Dataverse needs a user record bound to it, which is what turns the client id into an identity your environment recognizes.
- Sign in to the Power Platform admin center.
- Select Manage in the navigation pane, then Environments, then your environment.
- Select Settings > Users + permissions > Application users.
- Select + New app user.
- Select + Add an app and find your registration by name or by the client id from step 1, then select Add. Only Entra app registrations appear in this list — enterprise applications do not.
- Choose a Business Unit. The root business unit is the usual answer; a child unit narrows what the portal can reach even before security roles apply.
- Select the edit icon next to Security roles and assign the role you built for the portal — see the next step for what it needs to contain.
- Select Create.
Tip
An application user consumes no paid license, and you can only have one per Entra app registration per environment. Use a separate registration for each environment so that revoking development access never touches production.
5. Give the Application User a Security Role
Create a custom security role rather than reusing a built-in one, so the portal's access is visible and reviewable. What the role needs depends on which framework features you use:
| What the portal does | Access the role needs |
|---|---|
| Serves your portal's data | Create, Read, Write and Delete on every table your portal exposes, at the scope you intend visitors to reach. This is the bulk of the role, and it is entirely specific to your application. |
| Registers and signs in portal users | Create, Read and Write on contact, plus Create, Read, Write and Delete on adx_externalidentity, which stores the link between a portal user and an external login. |
| Binds grids to Dataverse views and formats values | Read on savedquery for the views your grids bind to, and Read on organization, usersettings and timezonedefinition so dates, numbers and currency format correctly. |
| Sends confirmation and password-reset email | Create, Read and Write on email, Create on activitymimeattachment, plus the Send Email and Send Email as Another User privileges. The sender address you configure is resolved to a queue or systemuser record, so the role also needs Read on those — which is why sending as that address counts as sending as another user. |
| Validates the website license | Permission to run the ppp_ProWebsiteLicenseCheck action and read the Portal Website records that ship in the managed solution. Without this, every licensed endpoint fails. |
| Dataverse-native security (optional) | Only if you enable the preview security model: Create and Read on systemuser, Read on businessunit, Create and Read on powerpagesusermapping, Read on powerpagesite and mspp_webrole, and the Act on Behalf of Another User privilege so the portal can impersonate each provisioned user. |
Important
Resist the temptation to assign System Administrator and move on. The portal is internet-facing, and this credential is the one that decides what an attacker reaches if the secret ever leaks. It is worth the afternoon it takes to build a real role — and a development environment is the right place to find out what you missed.
6. Store the Connection Settings
The portal reads these from configuration under the D365 section. Keep them in user secrets during development so they never reach source control:
{
"D365": {
"Url": "https://yourorg.crm.dynamics.com",
"ClientId": "<application (client) id>",
"ClientSecret": "<client secret value>",
"EmailSenderEmailAddress": "portal@yourcompany.com"
}
}
EmailSenderEmailAddress is the address the portal's outbound email is sent from. It must match a queue or an enabled systemuser in the environment — a queue is the usual choice, since it does not tie portal mail to a person who might later leave.
Tip
In hosted environments, supply the same keys as environment variables or from a secret store, using a double underscore in place of the colon —
D365__ClientId,D365__Secret— because the colon separator is not portable across platforms.
7. Wire Up the Connection
The server project configures ConnectionOptions when it registers the framework:
builder.Services.AddPowerPortalsProWebServer()
.Configure<ConnectionOptions>(options =>
{
options.AuthenticationType = AuthenticationType.ClientSecret;
options.ServiceUri = new Uri(builder.Configuration.GetRequiredValue("D365:Url"));
options.ClientId = builder.Configuration.GetRequiredValue("D365:ClientId");
options.ClientSecret = builder.Configuration.GetRequiredValue("D365:ClientSecret");
});
The project template writes this for you, so in a generated project there is nothing to add here — supply the three configuration values and the connection works. Start the portal and browse to any page backed by Dataverse data to confirm it.
Troubleshooting
- The caller is not a valid Dataverse user, or authentication fails outright. The app registration exists but no application user is bound to it in this environment. Application users are per-environment — creating one in development does nothing for production.
- Authentication fails with an invalid client secret. Usually the Secret ID was copied instead of the secret's Value, or the secret has expired. Create a new one and update configuration.
- A principal is missing a privilege. The application user's role is missing access to the table named in the error. Dataverse caches privileges per server node, so allow a minute or two after changing a role before concluding the change didn't help.
- Every data endpoint returns 402. The website license check is failing. Confirm the managed solution is installed, that a Portal Website record holds your license key, and that the application user's role can run
ppp_ProWebsiteLicenseCheck. - Email fails with “Unable to find an email sender with the email address”.
EmailSenderEmailAddressdoes not match any queue or enabled system user in the environment.
