Cross-tenant SharePoint permissions
Reference for how MigrationFox translates SharePoint permission assignments across two Entra ID tenants — the CSV mapping schema, how unmapped principals are detected and surfaced, when to invite a user as a B2B guest, and what happens to orphan permissions on the destination.
When to use this
Tenant-to-tenant SharePoint moves — acquisitions, divestitures, rebrands, and any site migration where the source and destination sit behind different Entra ID directories. Same-tenant migrations (site-to-site within one tenant) do not need CSV mapping because principals resolve natively.
The problem
A SharePoint permission is a triple: (principal, scope, role). When the source and destination live in the same tenant, the principal is the same Entra ID object on both sides and SharePoint resolves it natively. When the two sides live in different tenants, the source principal simply does not exist on the destination. alice@acme.com is a valid directory object in Acme’s Entra ID and has no meaning at all inside New Company’s Entra ID.
Copying the permission verbatim fails. The destination SharePoint site tries to resolve alice@acme.com against the tenant it lives in, finds nothing, and either rejects the assignment outright or writes a tombstone that breaks silently when Alice tries to open the site on Monday morning. The fix is to translate each source principal to the corresponding destination principal before the permission is written. That translation is what the mapping CSV provides.
Four categories of principal need translation, and each has a distinct failure mode:
- Individual users. UPN almost always changes across the tenant boundary (
alice@acme.com→alice.smith@newcompany.com). Requires an explicit row in the mapping CSV. - Security groups. The destination tenant has its own groups. Membership is a directory concern, not a migration concern — MigrationFox points permissions at the destination group; whoever maintains your Entra ID puts the right people in it.
- Microsoft 365 groups / Teams. Same as security groups, with the added ordering consideration that the group’s SharePoint site is often itself part of the migration wave.
- External guests and sharing links. Anyone-with-the-link sharing is policy-dependent on the destination tenant. B2B guests need an explicit invitation step.
CSV schema
Two CSV files drive the mapping. Both are uploaded once per migration wave on the job’s Permissions step. The files are small, human-readable, and edit-in-place so the team maintaining the directory can own them.
user-map.csv
One row per source user. Exact column names matter — the header is required and case-sensitive.
| Column | Meaning | Required |
|---|---|---|
source_upn | The user’s UPN as it exists in the source tenant’s Entra ID (for example alice@acme.com). | Yes |
destination_upn | The user’s UPN in the destination tenant’s Entra ID (for example alice.smith@newcompany.com). Must already exist as a directory object before replay runs. | Yes |
group-map.csv
One row per source group. Covers both security groups and Microsoft 365 groups. The same file handles both — the destination type is inferred from the destination tenant’s directory.
| Column | Meaning | Required |
|---|---|---|
source_group | Source group identity — the mail address for mail-enabled groups, or the group’s objectId for security-only groups. | Yes |
destination_group | Destination group identity in the same form. Must already exist and (for Microsoft 365 groups) be provisioned with a SharePoint site if you want the group’s site-level permissions to work. | Yes |
Group membership is not migrated
The mapping CSV tells MigrationFox which destination group to point a permission at. It does not populate the group’s members. Whoever maintains your Entra ID — typically IT via AD Connect, Okta, an HRIS integration, or a manual provisioning script — is responsible for ensuring the destination group contains the right users before replay runs. A mapped group with zero members results in a site where the permission is recorded but nobody has effective access.
Detection behavior
Permissions are the final phase of a SharePoint site migration, after every other piece of content and schema is in place. For each site, the sequence is:
- Enumerate source permissions. The scan walks the site’s role assignments at the site level, then every library, folder, and item with unique permissions (broken inheritance). Each assignment yields a (principal, scope, role) triple.
- Resolve each principal against the mapping. For every unique principal in the triples, MigrationFox performs one lookup against
user-map.csv(for users) orgroup-map.csv(for groups). A match produces the destination identity. A miss flags the principal as unmapped. - Produce the pre-flight exceptions list. Before any write occurs on the destination, the job’s Permissions page shows every unmapped principal together with the scopes and roles they held on the source. Each row has three actions: drop, invite as guest, or map inline.
- Replay mapped permissions. Each mapped triple is written to the destination against the translated principal. Throttle responses (429) back off exponentially, transient errors retry automatically, and terminal errors surface on the final report.
- Emit the audit report. A CSV record of every permission written, every permission skipped, and the reason for each skip. Downloadable from the job detail page and archived for tenant audit history.
Pre-flight is a hard gate. The job cannot advance from step 3 to step 4 until every unmapped principal has an explicit decision attached. There is no default fallback that silently drops permissions or invents identities based on fuzzy name matching — both outcomes produce sites that look fine and are actually half-broken.
B2B guest handling
The decision between mapping a source user to a native destination user versus inviting them as a B2B guest comes down to one question: does the user have an internal identity on the destination tenant?
Map to a native destination user
Use this path when the user is becoming an employee of the destination organization — typical during acquisitions, rebrands, and internal reorganizations. The destination UPN is an account on the destination’s own Entra ID directory. HR provisioned it through the usual joiner process. Add the row to user-map.csv and replay resolves it natively.
Invite as B2B guest
Use this path when the user is a real external collaborator — a partner firm, an agency, an auditor, a contractor whose primary identity lives elsewhere. The destination tenant does not and should not have an internal account for them. In the pre-flight exceptions list, select Invite as guest on the user’s row. During replay, MigrationFox:
- Sends a B2B guest invitation to the user’s existing email address.
- Creates (or reuses) a guest user object in the destination Entra ID.
- Applies the original source-side permission to that guest object on the destination site.
The guest invitation path is gated by the destination tenant’s external collaboration settings. If the tenant disallows guest invitations entirely, the Invite as guest option is disabled in the UI with an explanatory tooltip. If invitations are restricted to an allow-list of domains, a guest whose email is outside that list is flagged and cannot proceed until an admin updates the policy.
Decision shortcut
If the person’s email will be @newcompany.com after the move, map them. If it will stay @partnerfirm.com or @external.com, invite them as a guest. If they are leaving the business entirely, drop the permission.
Orphan permissions
When a source principal has no destination mapping and no guest invitation is issued, the permission is classed as an orphan. Orphans never get written to the destination site. The source assignment is recorded in the audit report with a reason code so compliance and security teams have a complete record of who had access to what on the source, but no ghost ACL is left behind on the destination pointing at a UPN that the destination directory cannot resolve.
Three orphan reason codes appear in the report:
dropped_leaver— the source principal is no longer employed and has no destination account. Access was going to end anyway; the migration simply does not carry it forward.dropped_explicit— a human operator reviewed the principal in pre-flight and chose Drop. Used when the source permission was legitimate at the time but is not needed on the destination (for example, a temporary contributor whose project ended).dropped_policy— the principal is a sharing surface (Anyone-with-the-link, a guest whose invite the destination tenant refuses) that the destination tenant’s policy will not reproduce. Dropping is the only safe outcome.
Orphans do not block the job. They are recorded, reported, and reviewable after the fact; a Monday-morning audit comparing the source ACL dump to the destination ACL dump will show exactly where each source assignment went.
Example user-map.csv
A realistic mapping for a small marketing team being moved from Acme into New Company during an acquisition. Covers the four common cases: employee transferring under a new UPN, employee transferring who also picks up a group assignment, external partner kept on as a guest, and a leaver whose access is intentionally dropped.
source_upn,destination_upn alice.finance@acme.com,alice.smith@newcompany.com bob.marketing@acme.com,bob.jones@newcompany.com carol.legal@acme.com,carol.davis@newcompany.com partner@external-agency.com,partner@external-agency.com ex-employee@acme.com,
How each row is handled in pre-flight:
- alice.finance → alice.smith — standard user-to-user mapping. Replays automatically.
- bob.marketing → bob.jones — user-to-user. Bob also inherits access to the marketing site through
group-map.csvonce the destination group is populated. - carol.legal → carol.davis — user-to-user. Name change (marriage) crossing tenant boundary; the mapping handles both the UPN change and the display-name change in one row.
- partner@external-agency.com → partner@external-agency.com — same email on both sides. The destination resolves this as an existing B2B guest (or creates one on first invite). In pre-flight, mark this row as Invite as guest to ensure the guest user object is provisioned before replay writes the ACL.
- ex-employee@acme.com → (empty) — an empty
destination_upnis the explicit signal to drop. Replay records the orphan with reasondropped_leaverand moves on.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Pre-flight shows every user as unmapped | CSV header mismatch. The column names are source_upn and destination_upn exactly — not Source UPN, not from/to. |
Check the header row case-sensitively. Save the file as UTF-8 without BOM — some spreadsheet exports write a BOM that breaks the first column header. |
| Replay writes the permission but the user cannot open the site | Destination UPN exists in Entra ID but has no SharePoint license, or the user has not signed into the destination tenant yet so the SharePoint profile is not provisioned. | Assign the SharePoint license and have the user complete their first sign-in. SharePoint provisions the user profile on first login; the ACL already points at the correct identity. |
| Mapped group resolves but members cannot access the site | Group exists on the destination but membership is empty or stale. Group membership is a directory concern, not a migration concern. | Populate the destination group through your directory tooling (Entra ID admin, AD Connect, Okta, HRIS). No migration re-run needed — the ACL already points at the group. |
| Guest invitation email never arrives | Destination tenant’s external collaboration policy blocks invites, or the guest’s email domain is outside the tenant’s allow-list. | Review the destination tenant’s external collaboration settings. Either relax the policy for the migration window, or add the partner’s domain to the allow-list. |
| “Anyone with the link” permissions all dropped | Destination tenant’s sharing policy is set to Existing guests only or stricter. Anyone-links are not reproducible under that policy. | Confirm the policy is intentional. If it is, the drops are correct — the audit report lists every file that had an Anyone-link so share owners can re-share explicitly to the right users afterwards. |
| Same user mapped but replay says “destination not found” | The destination UPN in the CSV is the user’s primary SMTP, not their UPN. In a tenant where these differ (common after a rebrand), SharePoint resolves against UPN. | Fetch the exact UPN from the destination Entra ID (PowerShell Get-MgUser or the admin center’s user detail page) and use that value in the CSV. |
What MigrationFox does not do
Mapping is an explicit act. MigrationFox does not fuzzy-match names (alice@acme.com looks like alison@newcompany.com is how security incidents start), does not create users or groups on the destination tenant, and does not populate group memberships. Those are directory tasks. The migration resolves permissions against identities that already exist.
Related
- SharePoint site migration overview — the full site migration lifecycle, of which permission replay is the final phase
- Migration Rehearsal dry-run — validate the mapping against a real site before the production cutover
- Microsoft: External collaboration settings — the tenant-level controls that govern B2B guest invitations