SYSTEM 8Discuss a system ↗
BLOG / POWER PLATFORM / RECORD SECURITY

FIELD NOTE / POWER PLATFORM / RECORD SECURITY

The Power Pages portal shows every record—or none

The prototype looked correct with an administrator account. External testing reveals the real problem: one permission change exposes other customers’ cases; the next change hides the user’s own case. Dataverse relationship and table-permission scope determine the exposed rows. The Dataverse model lacks the relationship path required by the portal security rule.

01

The niche portal failure

A programme portal lets property representatives submit an application, upload documents and track assessment. Each external organisation may have several contacts, and a consultant may act for more than one organisation. Internal staff use a model-driven app over the same Dataverse tables.

During the demo, the maker grants global read permission so the list renders. That exposes every application to every authenticated contact. Changing the table permission to Contact scope hides all records because the organisation team owns the applications and the signed-in contact has no qualifying relationship path. Adding ad hoc web roles produces a mix of empty lists and access denied errors.

The service allows a person to represent an organisation for a specific case, while the current Dataverse ownership model lacks that relationship. Security cannot be repaired reliably until that relationship becomes explicit data.

02

Model the access relationship first

Write the access rule in plain language for each persona. For example: “An authenticated representative may read applications for organisations where they hold an active representation record; they may edit a draft application they submitted; they may not read internal assessment notes.” Include start/end dates, delegation, staff override and what happens when representation is revoked.

Represent this relationship in Dataverse using deliberate tables and relationships. Do not infer it from email domain or a text organisation name. Decide whether Account/Contact relationships are sufficient or whether a junction table is required for many-to-many representation with status and validity dates.

Separate portal-facing fields from internal assessment fields. Field visibility is presentation. Underlying table and column rights decide access.

03

Build table permissions from the relationship

Choose the permission scope that follows the verified relationship: Contact for directly related personal records, Account for organisation records, Parent for traversal from an allowed parent, or Self for records the contact owns where that model is appropriate. Global scope is rarely acceptable for customer case data.

Associate table permissions with the minimum web roles. Trace every child permission and relationship name; a Parent permission pointing through the wrong relationship can either return nothing or broaden access. Keep create, read, write, append and append-to rights separate so an upload requirement does not accidentally grant case editing.

Apply server-side permissions even when lists and forms include filters. A view filter improves usability while another record URL remains callable. Table permissions must deny that request.

04

Use a negative-first test matrix

Create synthetic organisations A and B, contacts with single and multiple representation, an expired representative, an unaffiliated contact and an internal assessor. Seed draft, submitted and closed cases plus documents and internal notes. Test direct record URLs, list queries, forms, Web API calls and attachments.

Begin with what must fail: Contact A cannot read B’s case; an expired representative cannot open either the list or a bookmarked record; an external user cannot retrieve internal notes; an anonymous session cannot enumerate identifiers. Then prove the allowed actions.

Run each test with the specified portal identity. An administrator impersonation skips the external identity and table-permission path. Administrator success says nothing about table-permission correctness.

Run the direct-row negative test

GET /_api/new_cases({syntheticCaseGuid})
  ?$select=new_caseid,new_name,new_organisationid

Enable the Power Pages Web API only for the synthetic test table and selected fields, then remove or close the temporary diagnostic setting under change control. The entitled contact receives 200 with the expected case ID. An unrelated contact receives no row content. Repeat the direct URL, list query, lookup and attachment paths because a filtered view covers only the page query.

05

Diagnose empty results without switching to Global

When a legitimate user sees no records, inspect web-role assignment, table permission association, scope, relationship schema name, target record linkage and cache state in that order. Confirm the portal contact maps to the expected Dataverse contact and that the representation row is active.

Use Portal Checker and trace diagnostics where permitted, but keep test data non-sensitive. Clear or refresh the portal configuration cache through supported operations after permission changes; otherwise an old configuration can make a correct change appear ineffective.

Do not “temporarily” enable Global in production to prove the list works. That proves rendering while creating a disclosure path.

06

A controlled solution pattern

Use an authenticated portal contact linked to explicit organisation-representation records. Resolve visible cases through the approved Account/Parent relationship. Permit draft editing only while server-side status allows it, and move assessment notes to a table or column boundary not granted to portal roles. Store uploaded documents with a parent permission that cannot be traversed from unrelated cases.

For exceptional consultants acting across organisations, grant time-bounded representation records with an approver and expiry. Keep the global role out of the exception path. Provide internal staff with a separate model-driven security model and audited override process.

Document licensing and capacity assumptions against verified user and transaction volumes. A fit decision also requires verified support capacity and affordable licensing.

07

Acceptance and ongoing assurance

Automate the synthetic-persona matrix where feasible and rerun it after schema, web-role, table-permission or relationship changes. Add a release gate that fails on any cross-organisation read. Review representation expiry and exceptional access as business records with an approver, effective dates and retained audit events.

The design is accepted when allowed users can complete the hardest journey, prohibited users fail at every access path, support staff can explain why, and the evidence can be repeated after the next release.

08

Security anti-patterns to reject

Reject Global read used as a production troubleshooting switch, JavaScript-only filtering, security inferred from an email domain, and broad portal roles created for one exceptional consultant. Do not place internal assessment fields on a portal form and assume hidden controls protect them. Do not accept a test performed only by a system administrator.

Also reject permission designs that nobody can explain without opening the maker’s browser. The access path should resolve from a written business rule through explicit Dataverse relationships, table permissions and web roles to repeatable positive and negative tests.

When the requirement cannot be represented without brittle chains or custom code at every boundary, that evidence belongs in the platform-fit decision. A different architecture may satisfy the relationship and isolation requirements with fewer privileged workarounds.