In Part 1 we set up row- and column-level security for Jordan. In Part 2 we replaced individual assignment with HR Team and drew a Business Unit boundary between HR and Finance. In Part 3 we gave Morgan manager-level visibility through Security Role scoping, Parent:Child BU access, and Hierarchical Security.
Everything so far is structural — access follows ownership, team, Business Unit, or the org chart, all decided before a specific record exists. This post covers the case that doesn’t fit that mould: a one-off collaborator who needs exactly one record. Dataverse’s answer is record Sharing and Access Teams. We’ll also finally fix something flagged since Part 2: replacing Sam’s direct Finance Self-Service assignment with a Microsoft Entra ID group team.
Where We Left Off
| User | Business Unit | Team | Security Role source | Column Profile source | Can see Salary? |
|---|---|---|---|---|---|
| Alex | Root | — | System Administrator (direct) | Bypassed | ✓ Always |
| Jordan | Contoso - HR | HR Team | Employee Self-Service (via team) | HR Salary Access (via team) | ✓ Own row + team row |
| Morgan | Contoso - HR | HR Team | Employee Self-Service (via team) + HR Manager Self-Service (direct) | HR Salary Access (via team) | ✓ Own + Jordan + Riley + team row |
| Riley | Contoso - HR Trainees | — | HR Trainee Self-Service (direct) | None | ✓ Own row only |
| Sam | Contoso - Finance | — | Finance Self-Service (direct) | None | ✗ Blank |
Sam is still assigned Finance Self-Service directly — the “natural next step” flagged twice already.
The Plan
- Use record Sharing to give Sam one-off, read-only access to a single HR record
- Formalize that with an Access Team, managed from the record’s form instead of the Share dialog
- Replace Sam’s direct role assignment with a Microsoft Entra ID security group team
- Map every access path in the series onto exactly why Sam sees one HR row and nothing else
Why Sharing and Access Teams
Contoso runs a quarterly compensation review: Sam in Finance signs off on one specific HR salary record, not on HR’s salary data generally. Nothing built so far fits:
- Business Unit or Parent:Child BU access would show Sam every HR salary record, not just one.
- Adding Sam to HR Team hands him
Employee Self-ServiceandHR Salary Accesswholesale, forever. - Hierarchical Security doesn’t apply — Sam isn’t Jordan’s manager and never will be.
Sam needs a grant scoped to one record, independent of Business Unit, ownership, or the org chart.
Record Sharing
Sharing grants a specific user or team specific rights — Read, Write, Delete, Append, Append To, Assign, Share — on one record, independent of any Security Role.
Grant the Share privilege. Actor: Alex. Employee Self-Service currently has Share set to None. In the Power Platform admin center → Users + permissions → Security roles → Employee Self-Service → Employee Salary tab, set Share to User. User-level Share means Jordan can only share rows they own — not the whole Business Unit. This is the only step in this section that needs an admin — everything from here on, Jordan does herself.
Share Jordan’s row. Actor: Jordan. In make.powerapps.com → Tables → Employee Salary → Data, open Jordan’s row (it renders on the table’s Main form) → Share command in the command bar → add Sam → tick Read only.
Verify. Actor: Sam. In the same Tables → Employee Salary → Data grid, signed in as Sam: Jordan’s row now appears, read-only. Morgan’s and Riley’s rows are still invisible — sharing only touches the record it names.
The Salary column stays blank. Sam has row access via the share, but no HR Salary Access Column Security Profile, so the Salary value stays blank — same as on Sam’s own row. Row-level and column-level access are checked independently; both have to pass for a value to show.
Why this works. Dataverse checks two things: does Sam’s role grant any Read privilege on Employee Salary (yes — Finance Self-Service, at User scope), and does Sam have rights to this specific record (no, until the share supplies it). If Sam’s Read privilege were set to None entirely, sharing would do nothing — sharing extends a privilege the recipient already holds, it doesn’t create one from scratch. See Sharing and assigning and How access to a record is determined.
Revoking. Actor: Jordan. Same row, same Share command → select Sam → Remove. Refresh as Sam — the row is gone. Nothing about Sam’s role or team membership changed; the share was the only thing granting it.
Nothing here expires on its own. Until Jordan does the step above, Sam’s access to her row doesn’t lapse — there’s no built-in “this quarter only.” A manual share persists indefinitely until someone explicitly removes it. Keep that in mind; we’ll come back to it after Access Teams, since it’s true there too.
Where sharing runs out. This is fine for one record and one reviewer. It doesn’t scale to “every review record, every quarter, for whichever Finance approver is on rotation” — not because sharing itself is hard, but because someone has to remember the right rights (Read, not Write) every single time, using a generic dialog that doesn’t know this is a recurring reviewer pattern. That’s the problem Access Teams solve — not by removing the manual step, but by fixing the rights in advance and making the action itself harder to get wrong.
Access Teams — Sharing That Scales
An Access Team can’t own records or hold a Security Role — access teams do neither. Instead, a record is shared with the team, using rights defined by a reusable template wired into the record’s form, so anyone can add or remove a reviewer without ever opening the Share dialog.
To be precise about what’s actually improving here: an Access Team does not remove the manual step of adding Sam to a specific record — someone still does that, one reviewer at a time, same as a manual share. What it removes is the risk and repetition inside the Share dialog itself: rights are decided once, centrally, by whoever owns the template, and adding a reviewer becomes a single click on a list that’s already sitting on the record — not a separate dialog where someone has to remember which boxes to tick. It’s standardization and discoverability, not hands-off automation. The mechanism later in this post that removes the manual step entirely is the Microsoft Entra ID group team.
Enable Access Teams on the table. Actor: Alex. In make.powerapps.com → Tables → Employee Salary → Properties → Advanced options, toggle Access Teams on. This is a structural, one-way change to the table’s definition — decide it deliberately, not casually, in a production environment.
Create the template. Actor: Alex. Power Platform admin center → Settings → Templates → Access team templates → New:
| Field | Value |
|---|---|
| Name | Employee Salary Reviewers |
| Table | Employee Salary |
| Access Rights | Read only |
There’s no Create option on the list — an access team can never create records through its grant; that always requires the member’s own Security Role.
Add the control to the form. Actor: Alex. In make.powerapps.com → Tables → Employee Salary → Forms, open the table’s Main form. For this walkthrough, Employee Salary has a single Main form, named Information — if your table has more than one form in use, add this sub-grid to every form your record owners actually open, since a template only takes effect on the form you edit; Sam himself never needs this control on any form he uses, since he only ever views the row Jordan shares with him. On the Information form, select Components from the left pane (or the command bar) → select Subgrid → a New Subgrid dialog appears with the following fields:
| Field | Value | Why |
|---|---|---|
| Name | EmployeeSalaryReviewers | The internal schema name Dataverse uses to identify this sub-grid; it never appears to end users. The designer pre-fills a system-generated name like Subgrid_new_1 — replace it with something meaningful so it’s recognizable in solution XML, scripts, or form-level business rules later. |
| Label | Employee Salary Reviewers | The heading displayed above the sub-grid on the form at runtime. This is what Jordan sees when she opens a record, so it should clearly describe what the list is for. |
| Show related records | Unchecked | When checked, the sub-grid filters to child records that have a direct lookup back to the current record — useful for standard parent-child grids (e.g., Contacts on an Account). An Access Team sub-grid isn’t showing child records of Employee Salary; it’s showing Users who are members of a per-record team. Uncheck this so the Table and Default view dropdowns let you point at the Users table instead of being locked to tables related to Employee Salary. |
| Table | Users | Tells the sub-grid which table’s records to display. Access Team members are User records, so select Users here — not Employee Salary or any of its related tables. |
| Default view | Associated Record Team Members | The system view that filters the Users table down to only those users who are members of the per-record Access Team for this specific record. Without this view, the grid would show all Users in the environment instead of just the reviewers added to this row. |
| Team template | Employee Salary Reviewers | This dropdown appears only after the Default view is set to Associated Record Team Members. It wires the sub-grid to the template created earlier, so that clicking + Add on the grid automatically shares the record at the rights defined in that template (Read only, in this case) rather than requiring someone to configure rights manually each time. |
Click Done (or Add), then Save and Publish the form. Every Employee Salary record now shows an Employee Salary Reviewers list on that same Information form.
Grant the Append and Append To privileges. Actor: Alex. The sub-grid’s + Add button won’t appear unless two privileges are in place — Dataverse checks them as a pair for any record association. In the Power Platform admin center → Users + permissions → Security roles → Employee Self-Service:
- Employee Salary tab → set Append to User. The sub-grid lives on an Employee Salary form, so Append is checked here — it controls whether Jordan can create an association on her own Employee Salary records.
- Business Management tab (or whichever tab lists the User entity) → set Append To to Business Unit. The sub-grid adds User records, so Append To is checked on the User entity — it controls whether User records can be linked into the association. Set this on the User entity, not on Employee Salary — Append To on Employee Salary would control whether an Employee Salary record can be attached to something else, which isn’t what’s happening here.
Use Business Unit scope specifically, not Organisation. The User table is a Business-owned entity, not a User/Team-owned entity like Employee Salary, and the command bar’s enable rule for the + Add button does not recognise Organisation as satisfying a Business Unit depth check on Business-owned entities. Business Unit scope is also sufficient despite Sam being in a different BU — the button’s visibility is a privilege-presence check, and the actual cross-BU authorisation to add Sam comes from the Share privilege, not from the Append To scope.
The Share privilege set earlier (in the Record Sharing section) is also required here — adding someone to an Access Team is a share operation under the hood — but it’s already in place. If you skipped the Record Sharing section and jumped straight to Access Teams, go back and set Share to User as well.
Add Sam through the Access Team. Actor: Jordan. Back in make.powerapps.com → Tables → Employee Salary → Data, open Jordan’s row — it now renders the updated Information form with the Reviewers sub-grid on it → Employee Salary Reviewers → + Add → Sam. Dataverse creates a system-managed team scoped to this one record, adds Sam as its only member, and shares the row with that team at Read — exactly the right the template specifies. A different HR row gets its own, unrelated per-record team.
Verify. Actor: Sam. Same result as the manual share: Jordan’s row appears for Sam, read-only, in the same Tables → Employee Salary → Data grid. The Salary column is still blank — the Access Team grants row-level Read; it doesn’t touch the HR Salary Access Column Security Profile. Those two gates stay independent.
Check Access. Actor: Alex, or anyone troubleshooting on Jordan’s or Sam’s behalf. Every record’s command bar has a Check Access option. Run it for Sam on Jordan’s row and it reports exactly which paths grant visibility: the per-record team share, plus Sam’s baseline Finance Self-Service Read. It’s the fastest way to debug access without re-deriving it by hand.
Remove Sam Actor: Jordan. Remove Sam from the Reviewers list the same way as any sub-grid item — this unshares the row and Jordan’s row disappears for Sam again. As with a manual share, this removal has to happen explicitly: an Access Team membership doesn’t expire on a schedule. If Contoso wants access to lapse automatically once the quarterly review closes, that’s something to build separately — for example, a scheduled Power Automate flow that removes reviewers past a cutoff date. Out of the box, “this quarter only” is enforced by someone remembering to click Remove, exactly like the manual share earlier.
Why the Share privilege mattered here too. Adding someone to an Access Team is Dataverse sharing on your behalf, using the rights baked into the template. That’s why whoever does the adding needed Share privilege on the table, and why Sam still needed his own baseline User-level Read on Employee Salary for the grant to mean anything. In other words, the underlying grant is identical to a manual share — same row-level Read entry in Dataverse’s sharing records — the only difference is that a system-managed, per-record team now sits between Sam and the row, and its rights came from a template Alex set up once instead of being chosen ad hoc in the Share dialog every time. Both mechanisms require the caller to hold Share plus the template’s rights, and the recipient to already hold at least Basic Read — neither creates a privilege from nothing.
For the full solution-packaging version of these steps, see Create a team template and add it to an entity form.
Owner Teams vs Access Teams vs Microsoft Entra Group Teams
| Owner Team | Access Team | Microsoft Entra group team | |
|---|---|---|---|
| Can own records | Yes | No | Yes |
| Can hold a Security Role | Yes | No | Yes |
| Grants access via | Role privileges, team as record owner | A direct share of one record, at the rights in a template | Role privileges, evaluated like an Owner Team |
| Scope | Every record the team owns or has role-based access to | Only records explicitly attached to it | Every record the team owns or has role-based access to |
| Membership managed | Manually, in Dataverse | Manually or automatically per record | Automatically, from an Entra ID group |
| Best fit | A stable department with a fixed role | Ad hoc collaborators that change record by record | A department whose Dataverse membership should mirror an Entra ID group |
Only Owner Teams and Entra group teams can own records or hold Security Roles — Access Teams can do neither. That’s why HR Team had to be an Owner Team, and why the Reviewers pattern had to be an Access Team rather than a stripped-down Owner Team.
Finance is about to become the third type.
Microsoft Entra ID Group Teams — Automating Finance Membership
Finance Self-Service has been assigned to Sam directly since Part 2. An Owner Team for Finance would work, but it still needs Alex to remember to add and remove members by hand every time Finance hires or loses someone.
Contoso’s IT department already maintains a security group, Contoso Finance Employees, for licensing and Teams-channel access — Sam is already a member of it. A Microsoft Entra group team behaves like an Owner Team (it can own records and hold roles), except its membership is derived automatically from an existing Entra ID group, evaluated each time a member accesses the environment — no second, Dataverse-only list to maintain in parallel. Unlike the Access Team above, this really is hands-off: once it’s wired up, no one touches Dataverse to add or remove a Finance employee ever again.
If your environment restricts sign-in to a security group, make sure
Contoso Finance Employeesis nested inside that broader group too — otherwise new Finance hires still won’t be able to sign in, regardless of anything below.
Create the group team. Actor: Alex. Power Platform admin center → Users + permissions → Teams → + Create team:
| Field | Value |
|---|---|
| Team name | Finance Team (Entra ID) |
| Business Unit | Contoso - Finance |
| Team type | Microsoft Entra Security group |
| Group name | Contoso Finance Employees |
| Membership type | Members |
Membership type filters the Entra ID group, not Dataverse: Members pulls in only the group’s Members, excluding Owners and Guests. Separate group teams can target the same Entra ID group’s other facets — Contoso doesn’t need that split today.
Assign the Security Roles. Actor: Alex. Same Power Platform admin center screen: Finance Team (Entra ID) → Manage security roles → tick Finance Self-Service and Basic User. Same step Part 2 did for HR Team — only the team type is different.
Retire Sam’s direct assignment. Actor: Alex. Power Platform admin center → Users + permissions → Users → Sam → Manage security roles → untick both roles directly.
Verify. Actor: Sam, then Alex or Sam checking the result. Sign Sam out and back in — group membership is evaluated fresh each time a member accesses the environment. Back in make.powerapps.com → Tables → Employee Salary → Data, refresh: identical result to before — Sam’s own row, full Create/Read/Write, now sourced from Finance Team (Entra ID) instead of a direct assignment. The Read-only grant on Jordan’s row from the Access Team section is untouched — it lives independently in Dataverse’s sharing records, not tied to how Sam’s baseline role is delivered.
What changes going forward. Add a new hire to Contoso Finance Employees in the Entra admin center — no Dataverse step at all. The next time they sign in, they’re automatically a member of Finance Team (Entra ID) and hold Finance Self-Service and Basic User. Compare that to HR Team: onboarding a new HR employee still means Alex manually clicking + Add members in Dataverse, every time. Offboarding is the same story in reverse — remove Sam from the Entra ID group, and the next time he signs in, his access drops with it, no one having to remember to clean up an Owner Team.
What the Access Structure Looks Like Now
| User | Business Unit | Team(s) | Security Role source | Column Profile source | Per-record extras | Can see Salary? |
|---|---|---|---|---|---|---|
| Alex | Root | — | System Administrator (direct) | Bypassed | — | ✓ Always |
| Jordan | Contoso - HR | HR Team | Employee Self-Service (via team) | HR Salary Access (via team) | — | ✓ Own + team row |
| Morgan | Contoso - HR | HR Team | Employee Self-Service (via team) + HR Manager Self-Service (direct) | HR Salary Access (via team) | — | ✓ Own + Jordan + Riley + team row |
| Riley | Contoso - HR Trainees | — | HR Trainee Self-Service (direct) | None | — | ✓ Own row only |
| Sam | Contoso - Finance | Finance Team (Entra ID) | Finance Self-Service (via group team) | None | Read-only on Jordan’s row (Access Team) | ✗ Row visible, Salary blank |
Sam’s baseline Finance access now maintains itself through an Entra ID group instead of a direct role assignment. His visibility into one HR record comes from a mechanism that’s completely orthogonal to Business Unit, ownership, or role scope — a per-record Access Team grant that would still be there even if his Finance role changed entirely tomorrow, and that will keep being there until someone in HR explicitly removes it.
Things Worth Knowing
- Sharing and Access Teams both extend an existing privilege — neither creates one. Without at least User-level Read on the table, a share or access-team grant does nothing.
- The + Add button on an Access Team sub-grid requires Append on the parent table and Append To on the User entity — both, as a pair. Missing either hides the button silently. Set Append To on the User entity (Business Management tab) to Business Unit, not Organisation — the User table is Business-owned, and the command bar’s enable rule does not recognise Organisation as satisfying a BU depth check on this entity type. The cross-BU authorisation to add users from other Business Units comes from the Share privilege.
- Sharing never bypasses column security. A shared row with a secured column stays blank without the matching Column Security Profile — the two gates are always checked independently.
- Neither Sharing nor an Access Team grant expires on its own. “This quarter only” describes intent, not an enforced Dataverse behavior — Sam keeps Read access to Jordan’s row until Jordan (or Alex) explicitly removes him from the Share or the Reviewers list. If access genuinely needs to lapse on a schedule, that has to be built separately — for example, a Power Automate flow that removes reviewers past a cutoff date.
- An Access Team standardizes a manual step; it doesn’t remove it. Someone still adds each reviewer to each record. The Entra ID group team, further down, is the one mechanism here that removes the manual Dataverse step entirely.
- Only Owner Teams and Entra group teams can own records or hold roles. If a team should ever own something, it isn’t an Access Team.
- Team type is close to a one-way door. You can convert an Owner Team into an Access Team, never the reverse, and group teams can’t be converted at all — see Teams in Dataverse for the conversion command and its limits.
- A group team’s membership type is fixed at creation. Changing which Entra ID group facet (Members, Owners, Guests) feeds it means deleting and recreating the team.
- A user isn’t fully “in” Dataverse from an Entra ID group add alone. They won’t appear as a Dataverse user or team member until they’ve signed in to the environment at least once; their group-driven team membership and roles apply from that first sign-in.
- Group team membership can’t be managed inside Dataverse. Changes happen in Entra ID, by whoever administers that group — which may not be Alex.
- Business Unit and group-team membership are separate axes. Pointing a team at an Entra ID group automates role and team membership, not Business Unit — a genuinely new hire still needs to be placed in the right BU by hand.
- All sharing — manual or via an Access Team — lives in the PrincipalObjectAccess table. Environments with heavy sharing usage should periodically review this table’s growth rather than assuming sharing is free.
- Check Access is the fastest way to debug any of this — it reports ownership, team, BU, hierarchy, or a specific share in one place.
Where This Leaves Contoso
| Access mechanism | Introduced in | What it does in Contoso’s setup |
|---|---|---|
| Row-level security | Part 1 | Controls which rows each user can see, based on ownership and scope |
| Column-level security | Part 1 | Restricts the Salary column to users/teams with the HR Salary Access profile |
| Business Units | Part 2 | Draws the boundary between HR and Finance data |
| Owner Teams | Part 2 | HR Team carries both roles — one team, automatic onboarding |
| Member’s Privilege Inheritance | Part 2 | Determines whether team members see their own, team-owned, or both |
| Security Role scoping | Part 3 | The role’s BU field is governance; the access level is the actual control |
| Parent:Child BU access level | Part 3 | Gives Morgan Read into Contoso - HR Trainees without Organisation-level access |
| Manager Hierarchy | Part 3 | Morgan sees Jordan’s data via the reporting line, independent of BU |
| Record Sharing | This post | One-off, per-record, per-user Read grant — surgical and revocable, but manual and non-expiring |
| Access Teams | This post | Same underlying grant as Sharing, but with rights fixed in a reusable template and reviewer changes made from a list on the form instead of the Share dialog |
| Microsoft Entra ID group teams | This post | Finance’s Dataverse membership mirrors an Entra ID security group — the one mechanism here with no manual Dataverse step at all |
Sam seeing exactly one HR row — Jordan’s, read-only, Salary blank, until someone removes it — is four posts of these mechanisms working together: the Business Unit boundary holds everywhere it isn’t explicitly crossed, and the one place it’s crossed is scoped to a single record, revocable independently of everything else.
For anything not covered hands-on — auditing, custom code-driven security, Position Hierarchy, or the full six-layer model in one place — the Complete Guide is the reference to go back to.