Dataverse-Native Security Setup

Preview

This security model is currently in preview — both Microsoft's underlying unified Dataverse security feature and Power Portals Pro's support for it. Power Portals Pro follows Microsoft's release schedule: once the feature reaches general availability from Microsoft, Power Portals Pro's support will leave preview as well. The preview designation exists to account for any changes Microsoft may make on its side during the preview phase.

In this model the portal stops deciding what a user may do and Dataverse decides instead. Each portal contact is backed by its own Dataverse user, every request is made as that user, and access is whatever the security roles on that user allow — the same security model that governs a model-driven app. Nothing in the portal is consulted, and nothing in the portal can widen it. The catch is where those roles come from: Dataverse lets a provisioned portal user hold only a role the platform generated, and the only thing that generates them is Power Pages. So this one model does lean on Power Pages in a way the rest of Power Portals Pro never does — step 3 explains exactly how far that goes.

For how the model works and how it relates to permission handlers, see the Security overview

1. Install the Power Pages Framework Components

Backing a contact with a Dataverse user relies on a platform capability that only exists once Power Pages' components are in the environment: the system-managed user, a user record that costs no licence and exists to be impersonated. If the environment has never hosted a Power Pages site, create one now — any template works, and a trial site is fine. See Create and manage a site. Two things come out of those components: the user each contact is backed by, and the security roles that user is allowed to hold.

Note

You do not need to pay for the site or keep it running — after the framework components are installed and the security feature is enabled, you can delete the website itself. The Power Pages site record (powerpagesite) referenced by your configuration must remain, because each provisioned user is recorded against it in a powerpagesusermapping row — the link between a contact and the Dataverse user that stands in for it.

2. Enable Unified Dataverse Security for the Site

Enable Microsoft's unified Dataverse security feature for the site by following the steps in Unify Power Pages security with Dataverse. Once enabled, the platform creates a paired Dataverse security role (named PowerPages_*) for each web role on the site and keeps it in sync.

3. Grant Access with Web Roles and Table Permissions

Access comes from the security roles held by the Dataverse user behind each contact — but these are not roles you can write. Dataverse accepts only a system-generated role on a provisioned portal user, and the only thing that generates them is the feature you enabled in step 2: it creates a paired PowerPages_* role for each web role on the site, and the platform assigns and unassigns it as a contact's web-role membership changes. What a portal user can reach is therefore shaped by the web role and the table permissions attached to it — edited in the Power Pages Management app, or, with the Power Portals Pro Enhanced Authorization solution installed, on your portal's own Web Roles page. That is the one place in Power Portals Pro where a Power Pages concept decides what somebody can reach, and it is the platform's requirement rather than our design. Which records a user reaches is decided by each table permission's scope, not by ownership depth: every privilege on a generated role carries a platform record filter derived from it. Reading one table can reach into another — reading an account also reads its addresses — so those related tables need table permissions too. See Table permissions.

Note

Why you cannot just assign a role you made yourself. Verified in a clean environment: assigning an ordinary security role to a provisioned portal user fails with "The system managed user type is not valid for the role being assigned", and creating a role marked system-generated through the API is refused with "Invalid Operation performed." The restriction is specific to the user type the portal provisions — other system-managed users, such as an application user, hold ordinary roles without complaint.

4. Give Users Their Web Roles

A contact gets a web role's access by holding the web role. To hand web roles to new users automatically, install the Power Portals Pro Enhanced Authorization solution and add rules on your portal's Web Roles page (WebRoleAdmin, included in both project templates): each rule gives a web role to every new user, or to those matching a FetchXML rule over contacts. Rules run once per contact — when the portal registers it, and when an existing contact first signs in with an external login — so a web role an administrator later removes stays removed. You can also assign web roles by hand in the Power Pages Management app.

Note

The Enhanced Authorization solution is separate from Power Portals Pro Core because it depends on Power Pages. To assign web roles, the portal's application user needs Read on the Web Role Configuration table, Read and AppendTo on web roles, and Read, Append and AppendTo on site components (powerpagecomponent), where Power Pages stores web roles. The Web Roles page runs as the signed-in administrator, and Dataverse allows only what both they and the application user may do, so the application user additionally needs Create, Write, Delete and Append on the configuration table; Create, Write, Delete and Append on web roles; Create, Read, Write, Delete, Append and AppendTo on table permissions (mspp_entitypermission); Create, Write and Delete on site components; and AppendTo on websites (mspp_website), since every web role and table permission names the site it belongs to.

5. Find Your Power Pages Site Id

PowerPortalsPro needs the id of the site's powerpagesite record. You can query it directly — for example, open <your org url>/api/data/v9.2/powerpagesites?$select=name in a browser and copy the powerpagesiteid of your site.

6. Enable Provisioning in Power Portals Pro

Configure SecurityOptions in your server's Program.cs:

The configuration is validated at startup — when ProvisionSystemUsers is enabled, PowerPagesSiteId must be set and must resolve to an existing powerpagesite record, otherwise the application fails to start with guidance. From this point on, PowerPortalsPro automatically provisions a system-managed (C2) systemuser and a powerpagesusermapping record for every portal contact — at registration for new contacts, and lazily at sign-in for existing ones — and impersonates that user on every Dataverse call.

7. Check What a User Can Actually Do

A provisioned user is created the first time their contact signs in, so the quickest check is to sign in as a real portal user and try what they should and should not be able to do. Their access is exactly what their security roles allow: no portal-side configuration sits in front of it, and nothing in the portal widens it.

Tip

Dataverse caches each user's effective privileges per server node, so role and privilege changes can take from a few seconds up to a couple of minutes to take effect after an assignment. Account for this in tests and in any flow that grants access and then immediately acts on it.

Anonymous Visitors

Signed-out visitors are covered by the same mechanism. The platform creates an Anonymous system-managed user for the site — identity PowerPages_00000000-0000-0000-0000-000000000000@<site id>.com — and Power Portals Pro impersonates it for every unauthenticated request. Whatever security roles that user holds are what an anonymous visitor can reach, so give it the narrow, read-only access a signed-out visitor should have, and nothing more.

Note

The Anonymous user is created lazily by Power Pages, so sites created before the unified security feature may not have one yet (it is discovered through the site's contact-less powerpagesusermapping records — the user itself is invisible to attribute queries — and a candidate is only accepted after its identity is verified against the well-known Anonymous username). When it can't be found, anonymous visitors fall back to portal-side permission handlers — meaning no anonymous data access unless handlers are registered — and the framework logs the outcome at startup and keeps retrying periodically.

What About the Portal's Own Table Security?

Sessions under this model bypass everything a table registration describes — its operations, its columns, its row scope and its ownership stamping, whether you described them with AddTableAccess or wrote an ITablePermissionProvider — exactly like internal systemuser sign-ins, because Dataverse is enforcing instead. Which rows a user reaches and who a record they create belongs to are their security roles' to decide, like everything else. You don't need to write or register any of it. Registrations still gate sessions that are not backed by a provisioned user (the feature disabled, a session where provisioning failed and the framework fell back to portal-side security, or anonymous visitors on a site without the Anonymous user), so existing portals can migrate incrementally. Portal roles don't apply to these sessions either: they are neither assigned nor read under this model.

Distinguishing Provisioned Users in Your UI

Sessions carry a PortalUserType claim holding the integer value of the PortalUserType enum: Contact (classic portal user), SystemUser (real internal sign-in), or ContactStubUser (a contact backed by a provisioned system-managed user); ContactStubUser sessions additionally carry a SystemUserId claim with the provisioned user's id, resolved from the authoritative powerpagesusermapping record. The same enum is returned by GET /api/auth/me as CurrentUserResponse.PortalUserType. Use the GetPortalUserType() and GetDataverseSystemUserId() extensions on ClaimsPrincipal, and never present a ContactStubUser session as an internal user.

Role claims follow the same model. A provisioned user's session carries the web roles they hold — the names an administrator assigned — together with the PowerPages_* security roles paired with them, and no portal roles. Gate on web roles with [AuthorizeWebRole("Dealers")] or <PortalRoleView WebRole="Dealers"> in Blazor, and <AuthorizedView webRoles="Dealers"> in React; GET /api/auth/me lists them as webRoles.

API Reference

DataverseSecurityOptions Class

Properties

Name
Type
Default
Description
PowerPagesSiteIdGuid?
The id of the powerpagesite record that provisioned powerpagesusermapping rows reference. Required when DataverseSecurityOptions.ProvisionSystemUsers is enabled — the mapping technically accepts a null site, but security-role sync does not function without one.
ProvisionSystemUsersbool
False
When true, a system-managed (C2) systemuser and a powerpagesusermapping row are automatically provisioned for each portal contact (at registration, and lazily at sign-in for pre-existing contacts), and Dataverse calls for the session impersonate that user so Dataverse enforces its security roles natively. Requires DataverseSecurityOptions.PowerPagesSiteId; validated at application startup.
Name: PowerPagesSiteId
Type: Guid?
Description: The id of the powerpagesite record that provisioned powerpagesusermapping rows reference. Required when DataverseSecurityOptions.ProvisionSystemUsers is enabled — the mapping technically accepts a null site, but security-role sync does not function without one.
Name: ProvisionSystemUsers
Type: bool
Default: False
Description: When true, a system-managed (C2) systemuser and a powerpagesusermapping row are automatically provisioned for each portal contact (at registration, and lazily at sign-in for pre-existing contacts), and Dataverse calls for the session impersonate that user so Dataverse enforces its security roles natively. Requires DataverseSecurityOptions.PowerPagesSiteId; validated at application startup.