Power Pages security: table permissions and web roles
Understand how Power Pages decides who sees which Dataverse rows, choose the right access type, and avoid the most common security mistakes.
What you'll learn
- How web roles and table permissions work together
- Choose between Global, Contact, Account, Self and Parent access
- Secure lists, forms and the portal Web API
- Test as different users before go-live
On this page
Power Pages exposes Dataverse data to people outside your organisation, so security has to be right. Two concepts control everything: web roles and table permissions.
How it fits together
- A contact (the signed-in site user) is assigned one or more web roles.
- Table permissions are attached to web roles.
- A table permission says which rows (access type) and what actions (read, create, write, delete, append) are allowed.
No table permission means no data — lists and forms simply show nothing. That's the safe default.
Choose the access type
| Access type | Rows the user can access | Example |
|---|---|---|
| Global | All rows in the table | Public product catalogue |
| Contact | Rows linked to the user's contact | "My support cases" |
| Account | Rows linked to the user's parent account | "My company's orders" |
| Self | The user's own contact record | Profile page |
| Parent | Rows related to a parent permission | Case notes under "My cases" |
Example: customers see only their cases
- Create a web role called Customer.
- Create a table permission on Case with access type Contact, using the relationship between Case and Contact, and grant Read and Create.
- Create a child permission on Note with access type Parent, linked to the Case permission, so users can see notes on their own cases only.
- Assign the Customer role to authenticated users.
The portal Web API
If you use the Power Pages Web API from JavaScript, table permissions still apply — but you must also enable the table and list the allowed fields with site settings:
Webapi/incident/enabled = true
Webapi/incident/fields = title,description,statuscodeList specific fields instead of *, so a new sensitive column is never exposed by accident.
Test before go-live
Create test contacts for each role — a customer, a partner, an anonymous visitor — and sign in as each. Check every list, form and page. It takes an hour and catches problems that would otherwise reach real customers.