M365Con 2027 – free online conference · 11–22 Jan 2027 · 120 sessions→ m365con.net

2025-08-08

Build Customer Portals with Power Pages and Dataverse

Build Customer Portals with Power Pages and Dataverse
Stop emailing Dataverse exports. Build a branded, secure, customer-ready portal with Power Pages that shows the right records to the right people—nothing more. This guide gives you a step-by-step build, least-privilege web roles/table permissions, and a go-live checklist (auth, data scope…
ower Pages Customer Portal — Field Guide

What you’ll build (at a glance)

  • Auth: External identities (Azure AD B2C or local) + MFA

  • Access: Web roles (Customer / Partner / Manager) mapped to Dataverse table permissions with Contact/Account scope

  • Data: Read/write only to the user’s own records; sensitive columns masked

  • Branding: Your domain, colors, logos, emails, and error pages

  • Audit: Sign-in logs, data access logs, and change history wired up


Step-by-step (secure by default)

  1. Plan data boundaries (15 min)

    • List the Dataverse tables you’ll expose and the minimum actions: Read | Create | Update | Append.

    • Decide row scope per table: Contact (only my records), Account (my company’s records), Global (public/KB only).

  2. Create a Dev environment + Power Pages site

    • Separate Dev/Test/Prod. Disable indexing while in Dev.

  3. Choose authentication (customers)

    • Recommended: Azure AD B2C (supports social logins + MFA + self-service).

    • Small/temporary: Local auth with strong password/MFA + email verification.

    • Turn OFF anonymous access unless it’s a public KB.

  4. Wire identities

    • Map portal users to Dataverse Contacts.

    • Enable email verification and password reset flows; add custom sender domain.

  5. Define web roles (least privilege)

    • CustomerUser – sees own records (Contact scope).

    • AccountManager – sees own account’s records (Account scope).

    • SupportAgentExternal (optional) – specific tables with broader read.

    • Avoid using the default “Authenticated Users” for production.

  6. Add tables (carefully)

    • In Power Pages Studio → Data → Add table.

    • Immediately set Table Permissions: scope + CRUD per role.

    • Never set Global unless data is truly public.

  7. Harden field-level visibility

    • Hide PII fields from forms/lists.

    • Use column-level security or separate a “PublicView” with safe columns only.

  8. Build pages, lists, and forms

    • Use filtered lists (e.g., Created By (Contact) = Current User).

    • Validate server-side with Dataverse rules; add client checks for UX only.

  9. Branding & trust

    • Custom domain + SSL, logo, colors, typography.

    • Branded sign-in/reset pages + branded emails (DKIM/SPF set).

    • Accessibility (WCAG AA): contrast, focus states, alt text, keyboard nav.

  10. Instrumentation & audit

    • Turn on portal diagnostics, Application Insights, and sign-in logs.

    • Add correlation IDs to error pages; set up alert rules for 4xx/5xx spikes.

  11. Pen-test your permissions

    • Test as each web role: confirm you can’t see other Contacts/Accounts.

    • Try direct URL/ID tampering on list/detail pages.

    • Review audit logs after tests.

  12. Promote to Test → Prod

    • Export as managed solution.

    • Rebind environment variables, site settings, and identity providers per env.

    • Smoke test, then schedule a soft launch.


Baseline permission model (starter)

Web Role Tables (example) Scope Perms
CustomerUser Case, Order, Invoice Contact Read, Create (Case)
AccountManager Case, Order, Invoice Account Read, Update (Case)
KnowledgeBaseViewer Article Global Read
VendorUser (opt.) Delivery, ASN Account Read, Update (Delivery)

Add separate Admin (internal) only if truly needed; keep it out of external roles.


Auth choice quick matrix

  • Azure AD B2C (best general choice)

    • ✅ MFA, social logins, self-service, scale

    • 🔧 Initial setup + custom policies/branding

  • Local Accounts

    • ✅ Quick start, small audiences

    • ⚠ You own password resets, MFA, deliverability, breach notifications

  • External IdPs (Google/Apple)

    • ✅ Frictionless sign-in

    • ⚠ Compliance/data residency checks; align privacy disclosures


Go-live checklist (copy/paste)

  • Anonymous access OFF (unless public KB)

  • Custom domain + SSL bound

  • Branded sign-in/reset pages + verified sender domain

  • Web roles documented; defaults removed from users

  • Table permissions set with Contact/Account scopes

  • Sensitive columns excluded or masked

  • URL tampering tests (GUID swaps) blocked by server filters

  • App Insights + alerts; sign-in logs reviewed

  • Content Security Policy tightened (no *)

  • Managed solution deployed; env variables set; secrets in Key Vault

  • Accessibility pass (WCAG AA)


Useful snippets & settings

Table Permission examples

  • Case (CustomerUser): Scope=Contact, Perms=Read, Create (limit fields), Append To: Contact

  • Case (AccountManager): Scope=Account, Perms=Read/Update, Append To: Account

  • Invoice: Scope=Account, Perms=Read (no Create/Update)

Site settings to review

  • Authentication/OpenRegistrationEnabled = false (if invite-only)

  • Authentication/Registration/Email = true

  • Webapi/EnableReadOnly = true (tighten further per need)

  • Site/EnableCustomErrors = true (no stack traces to users)

Content Security Policy (tight start)

default-src 'self'; img-src 'self' data:; script-src 'self' 'sha256-…'; style-src 'self' 'unsafe-inline'; connect-src 'self' https://*.yourtenant.crm*.dynamics.com; frame-ancestors 'self' https://yourdomain.com;

Ops runbook KPIs

  • Auth health: Success rate, MFA drop-offs, password reset failures

  • Data access: 4xx (forbidden) spikes, RBAC drift (unexpected role mix)

  • Performance: P95 page load, list query duration, form save latency

  • Security: CSP violations, WAF hits, unusual geo sign-ins

  • Adoption: DAU/MAU, case creation rate, time-to-resolution


1-week rollout plan

Day 1: Scope tables & actions; draft web roles
Day 2: Stand up Dev site; configure B2C/local auth; disable anonymous
Day 3: Add tables + table permissions; hide sensitive fields
Day 4: Build lists/forms with filtered views; brand sign-in/reset
Day 5: Instrumentation (App Insights); pen-test row/field access
Day 6: Move to Test (managed); rebind settings; UAT with 5 pilot users
Day 7: Cutover to Prod; enable alerts; soft launch + feedback loop


Avoid these gotchas

  • Leaving “Authenticated Users” with broad access—create specific roles.

  • Using Global scope where Account/Contact is intended.

  • Exposing sensitive columns in list views (even if hidden on forms).

  • Relying on client-side filtering only—enforce on server via permissions.

  • Launching without branded comms (welcome/reset emails land in spam).


If you want, I can tailor a role & permission matrix to your exact tables and sketch the managed solution structure (Dev → Test → Prod), plus an invite email template your brand team can drop in.

Apple Podcasts · Spotify · YouTube

Host: Mirko Peters

Related articles

← Predictive Lead Scoring with Dynamics 365Extend Microsoft Fabric with Custom APIs and Power BI Models →