Learn how to secure your model-driven app from the ground up. This lesson walks through creating security roles, applying column-level security profiles, and using team-based access — so the right people see exactly the right data.

Imagine you've built a polished model-driven app for your sales organization. The app tracks leads, opportunities, and customer contracts — complete with sensitive fields like deal value, commission rates, and legal terms. Your sales reps should be able to create and edit their own opportunities. Sales managers should see everyone's records but only be able to delete their own. The legal team needs read-only access to contracts. And under no circumstances should a rep see another rep's commission rate.
Without a security model, everyone sees everything. That's not just a privacy problem — it's a compliance problem, a trust problem, and eventually a people problem when someone accidentally edits a colleague's deal or deletes a record they shouldn't have touched.
Model-driven apps built on Dataverse have a rich, layered security system built in. By the end of this lesson, you'll know how to use that system to implement exactly the kind of access control described above — without writing a single line of code. You'll configure security roles that define what users can do with each table, apply field-level security profiles to protect individual columns, and set up team-based access to handle scenarios where groups of users share ownership over records.
What you'll learn:
Before diving in, you should have a basic understanding of how Dataverse tables, rows, and columns work. If you're new to those concepts, read Dataverse Fundamentals: Tables, Columns, and Rows Explained for Power Apps Makers first. You should also have at minimum a working model-driven app — if you haven't built one yet, Building Your First Model-Driven App: Site Map, Tables, Forms, and Views will get you there. You don't need to be a system administrator, but the exercises in this lesson require that level of access in a Dataverse environment.
Before touching any settings, you need to internalize one principle that governs everything else: Dataverse security is additive. Users get the union of all privileges granted to them across all their assigned roles. There's no "deny" — only "allow" or "not allowed." If a user has two roles and one grants Read access to the Opportunity table while the other doesn't mention Opportunity at all, the user can read Opportunities.
This means you can't use a role to take something away from a user who already has it through another role. Instead, you design roles to grant only what each group of users needs, and you combine them deliberately.
The security system has three main layers:
Let's build each layer from the ground up.
A security role is a named collection of privileges. Every user in Dataverse must have at least one security role assigned (directly or via a team) or they won't be able to do anything in the system — they won't even see the app.
Each table in Dataverse supports eight privileges:
For each privilege, you choose an access level (sometimes called scope) — a circle icon in the role editor that ranges from no access to full organization-wide access:
Think of these as concentric rings of visibility. User is the smallest ring (just you), and Organization is the largest ring (everyone).
Navigate to the Power Platform Admin Center at admin.powerplatform.microsoft.com. Select your environment, then go to Settings → Users + permissions → Security roles. Click New role.
Give your role a meaningful name that reflects the job function it serves, not a technical label. "Sales Representative" is a better name than "Role_SR_001". Set the Business Unit if needed — in most cases you'll leave this as the root business unit so the role is available across the organization.
You'll see a grid of tables across the top and privilege types down the side (or you can switch to the table view). Each cell shows a circle — clicking it cycles through the access levels from None (empty) to Organization (filled). The visual makes it easy to see at a glance what a role grants.
Tip
The role editor has both a "classic" view and a modern simplified view in some environments. The classic view gives you the most control and shows all eight privileges. If your view looks simplified, look for a "Switch to classic" link or use the classic role editor via the legacy interface at https://[your-environment].crm.dynamics.com/main.aspx?pagetype=roles.
Let's configure the Sales Representative role for the scenario described in the introduction. Set these privileges on the Opportunity table:
For the Contact table (which Opportunities link to), give Read at Business Unit level and Write at User level. For Account, Read at Business Unit. You don't want a rep accidentally editing an account they don't own.
Warning
Don't forget the Append and Append To privileges. These control whether related records (like Activities, Notes, and related table rows) can be linked together. A very common beginner mistake is giving Read/Write but leaving Append and Append To empty, then wondering why related records won't save.
For the Sales Manager role, increase the scope:
Rather than rebuilding from scratch, you can copy an existing role — find it in the Security Roles list, select it, and click Copy. This is a huge time saver when roles are related.
Note
Dataverse ships with a set of built-in roles like "Salesperson," "Sales Manager," and "System User." You can examine these for inspiration, but don't assign them to your users without auditing them first. They're fairly permissive and often grant more access than you want.
Once roles are created, go to Settings → Users + permissions → Users in the Admin Center. Select a user and click Manage security roles. Check the boxes for each role they need, then save.
A user can hold multiple roles simultaneously. If your Sales Manager is also a Power Platform admin during a rollout period, they might hold both "Sales Manager" and "System Administrator" temporarily — and the system admin role will grant them everything. Always audit role assignments after rollout.
A business unit is Dataverse's organizational container for users and records. Every user belongs to exactly one business unit. Records owned by a user inherit that user's business unit, which is what makes the "Business Unit" access level meaningful.
If your company has a North America team and a Europe team and they should never see each other's data, you'd create two child business units under the root. Users in the NA business unit with "Business Unit" Read access to Opportunity would see NA opportunities, but not EU ones.
Key insight
Business units affect data visibility at the row level. If you don't set up business units deliberately, everyone sits in the root business unit — which means "Business Unit" access level effectively becomes the same as "Organization" access. Plan your BU structure before assigning roles, not after. For a deeper treatment of this topic, see Dataverse Security: Business Units, Security Roles, and Teams.
Security roles handle table-level access. But what about individual fields? In our sales scenario, we said reps should never see the Commission Rate column on Opportunity records. Even if a rep has Read access to the Opportunity table, we can hide — or make read-only — specific fields using Column Security Profiles (also called Field Security Profiles).
Column-level security is not on by default. You have to enable it per column. Here's how:
Once column security is enabled on a field, the field becomes invisible to everyone by default until they're explicitly granted access via a Column Security Profile. This is the opposite of the table-level security model, where access is additive. With column security, the default becomes restrictive.
Warning
As soon as you enable column security on a field, any user who previously had access through their role will lose visibility of that field — even system administrators viewing data through the app. System admins can still see the field via the Admin Center and API, but not in the model-driven app UI. Plan your profiles before enabling column security on live data.
In the Power Platform Admin Center, go to Settings → Users + permissions → Column security profiles. Click New Profile.
Name it descriptively: "Commission Rate — Manager View" or "Commission Rate — Read Only."
After saving the profile, open it and go to the Column permissions tab. You'll see all the columns in your environment that have column security enabled. Find Commission Rate (it'll be prefixed with the table name) and click to add a permission. You'll choose:
For a profile that gives Sales Managers full access to commission rate: Read Yes, Create Yes, Update Yes. For a profile that gives Legal read-only access: Read Yes, Create No, Update No. For Sales Representatives: don't add the commission rate column to their profile at all — they simply won't see it.
Go back to the Column Security Profile, open the Users tab, and click Add Users to assign individual users. Or go to the Teams tab to assign the profile to a team (more on teams below — this is where things get powerful).
For a deep look at the mechanics and edge cases of column-level security, Column-Level Security and Record Sharing in Dataverse covers scenarios like what happens when a field is on a required form or used in a business rule.
You've configured roles for individuals. But real organizations have collaborative workflows where groups of people need to share access to records that might be owned by a single user. That's where Teams come in.
Dataverse supports three types of teams:
In the Admin Center: Settings → Users + permissions → Teams. Click Create team.
After creation, add members on the Members tab. Then go to the Security Roles tab and assign the Sales Representative role to the team. Every member inherits this role through team membership.
Tip
Assigning roles to teams rather than individual users simplifies administration enormously. When a new rep joins, add them to the team — they immediately get the right role. When they leave, remove them from the team. You don't have to remember which roles to add or remove.
For enterprise environments, Entra ID Group Teams are the gold standard. Instead of managing team membership manually in Dataverse, you rely on your IT team's Azure AD group management processes.
When creating the team, choose Microsoft Entra ID Security Group or Microsoft 365 Group as the team type, then provide the Object ID of the Azure AD group. Dataverse syncs membership automatically.
Assign your Dataverse security roles to this team, and every Azure AD group member picks up those roles when they authenticate. This means your access control policy lives in one place (Azure AD), and Dataverse respects it.
Access teams work differently — they're created per-record rather than globally. For example, when a high-value opportunity goes into legal review, you might want to give three people from the legal team access to just that specific record, without changing their global role.
To enable access teams on a table, go to the table settings in make.powerapps.com → Tables → Opportunity → Properties → Advanced options and enable Access teams. You then define an Access Team Template that describes what privileges members of the team will have on that record.
In the app, a subgrid on the Opportunity form will let users manage the access team for that record. This is powerful but more complex to set up — use access teams when you genuinely need per-record collaboration that can't be handled by role scoping.
Let's put it all together with a scenario. Sarah is a Sales Representative. She has:
Mike is her Sales Manager. He has:
Can Sarah read Mike's Opportunity records? Sarah has Business Unit Read access on Opportunity. If Mike is in the same business unit, yes — Sarah can read Mike's records.
Can Sarah edit Mike's Opportunity records? Sarah has User-level Write on Opportunity — only her own records. So no, she can't edit Mike's.
Can Sarah see the Commission Rate field on any Opportunity? Column security is enabled on Commission Rate and Sarah has no profile granting her access. She won't see the field at all — not on forms, not in views. It's completely hidden.
Can Mike see Sarah's Commission Rate? Yes — Mike has Business Unit Read on Opportunity (covering Sarah's records) and his Column Security Profile grants him Read on Commission Rate.
Can Mike delete Sarah's Opportunity? Mike has User-level Delete — only his own records. He can't delete Sarah's.
This kind of layered reasoning is how security architects think through access models. The key is to work through each combination deliberately rather than assuming.
Key insight
Build a simple matrix when designing your security model: list your user roles as rows and key operations (Read Own, Read Others, Write Own, Write Others, Delete, See Field X) as columns. Fill in Yes/No for each combination. This makes gaps and conflicts obvious before you configure anything.
For this exercise, you'll need a Dataverse environment with system administrator access and an existing Opportunity table (or any custom table you've created).
Scenario: You're securing an app for a small consulting firm. Consultants can create and edit their own project records. Practice Managers can read and edit all project records in their business unit. The "Billing Rate" field should be visible to Practice Managers but hidden from Consultants.
Step 1: Create two security roles
Navigate to Admin Center → Settings → Users + permissions → Security roles → New role.
Create "Consultant" with these privileges on your Project table: Create (User), Read (Business Unit), Write (User), Delete (User), Append (User), Append To (Business Unit).
Create "Practice Manager" with: Create (Business Unit), Read (Business Unit), Write (Business Unit), Delete (User), Append (Business Unit), Append To (Business Unit), Assign (Business Unit), Share (Business Unit).
Step 2: Enable column security on Billing Rate
Go to make.powerapps.com → Tables → Project → Columns → Billing Rate → Advanced options → Enable column security → Yes → Save.
Step 3: Create a Column Security Profile for Practice Managers
Admin Center → Settings → Users + permissions → Column security profiles → New Profile → Name it "Billing Rate — Practice Manager." Add the Billing Rate column permission with Read Yes, Create Yes, Update Yes. Add a test Practice Manager user on the Users tab.
Step 4: Assign roles to test users
Create two test users (or use existing ones) in your environment. Assign "Consultant" to one and "Practice Manager" to the other. Sign in as each user and verify: the Consultant cannot see the Billing Rate field; the Practice Manager can see and edit it.
Step 5: Create an Owner Team
Admin Center → Teams → Create team → Name it "Practice Team Alpha" → Type: Owner → Assign the "Consultant" role to the team → Add your Consultant test user as a member. Verify the user's role comes through team membership.
"My user can't see any records even though I gave them Read access." Check that the user has the System User role in addition to your custom role. The System User role grants basic environment access and must be present. Also check the access level — if you set User scope on Read, they can only see records they own.
"I enabled column security but now my business rule is broken." Business Rules in Dataverse: Validation and Field Logic Without Code explains that business rules evaluate in the context of the current user. If the column is hidden due to column security, rules that depend on reading or setting that field may behave unexpectedly. You may need to move logic to a server-side plugin or Power Automate flow.
"I assigned a role to a user but they still can't access the app." Check whether the model-driven app itself has been shared with the user. App sharing and role assignment are separate steps. In make.powerapps.com, open the app, click the three dots, and choose Share — then add the user.
"A user says they can see records they shouldn't be able to." The most common cause is a second role with broader access. Pull up the user's role assignments in the Admin Center and audit every role they hold. Remember — security is additive. Also check if they're a member of a team that holds a broader role.
"Column security is enabled but everyone can still see the field." You created the profile but may not have assigned it to any users or teams. A column security profile does nothing until it's assigned. Go back to the profile and verify the Users and Teams tabs are populated.
You've learned how Dataverse's layered security model works and how to implement it in practice. Security roles define table-level privileges and scopes — they answer the questions "what can you do?" and "on whose records?" Column Security Profiles answer "what fields can you see and edit?" Teams answer "how do groups of users share ownership and access?" And all of these layers stack additively, so the key discipline is designing roles with the minimum necessary privilege and auditing the combinations.
The logical next step is to look at the more advanced scenarios that come up in real deployments: sharing individual records with specific users outside of roles, cascading delete and sharing behavior, and how the auditing and change tracking features give you a way to prove your security model is working. When you're packaging your security configuration for deployment across environments, Solutions for Model-Driven Apps: Publishers, Managed vs Unmanaged, and Solution Layering explains how security roles travel in solutions — including the important difference between how managed and unmanaged solutions handle role customization.
Security isn't glamorous, but it's the foundation that makes everything else trustworthy. Get it right early, document your role matrix, and your users will interact with your app with confidence — knowing they see exactly what they should, and nothing they shouldn't.