TECHNICAL · July 12, 2026 · 10 min read
SharePoint Cross-Tenant Migration: The Permission Mapping Problem
Every consultant who has run a tenant-to-tenant SharePoint migration has seen it: the copy job succeeds, the files land at the destination, the folder tree looks perfect — and every permission is silently missing or wrong. The users on the destination side either can't access files they should own, or they can, but only because the migration granted "Everyone" by default and now compliance wants to know why.
The root cause isn't the migration tool. It's how identity works across tenants. This article explains why cross-tenant permissions break, why the naive approaches fail, and the mapping-table pattern that actually works — including what's supported in MigrationFox today.
Why Cross-Tenant Permissions Break
Within a single tenant, permissions are stored as UPNs (user principal names) or SIDs pointing at Azure AD identities. When a file's ACL says jsmith@contoso.com has Read, SharePoint resolves that against the tenant's directory in real time. Everything works because the identity exists in the same directory the ACL was written into.
Cross-tenant, the identity doesn't exist. When you copy a file's ACL from contoso.com to fabrikam.com, the destination tenant has no idea who jsmith@contoso.com is. There are three failure modes SharePoint picks between, and none is what you want:
- Silent drop. The ACL entry is discarded on write. The file lands with no unique permissions, inheriting whatever the parent library grants. Usually this means the wrong people can see it.
- Broken principal. The ACL entry is written literally as the source UPN string. The permission "exists" but points at nobody — it appears in permission reports but grants no access. Compliance teams find these years later during an audit and can't explain them.
- Everyone bypass. Some naive migration approaches, on failure to resolve, apply "Everyone except external users" as a fallback. Everything works — too well.
All three are failures. The migration tool didn't know what to do because you didn't tell it. You need to bring the mapping.
What Doesn't Work
"SharePoint will figure it out"
SharePoint doesn't. It has no visibility into your source tenant's directory. Its identity resolver only queries the local Azure AD. There's no cross-tenant lookup mechanism for arbitrary UPNs. This is by design — you don't want contoso.com's files granting access to arbitrary Azure AD identities they haven't invited.
"We'll match on display name"
Every large organization has multiple John Smiths. Any migration that resolves by display name will assign permissions to the wrong person eventually. Legal teams hate this even more than lost permissions.
"We'll invite everyone as guests first, then migrate"
Guests get external-user UPNs like jsmith_contoso.com#EXT#@fabrikam.onmicrosoft.com. The ACL entries from the source still say jsmith@contoso.com. Same problem, different letters. You still need a mapping table to convert one to the other.
"The users have the same email in both tenants, it should just work"
Only if the destination tenant has been provisioned with users at those exact UPNs before the migration runs. Most consolidation projects have jsmith@oldcompany.com at the source and john.smith@newcompany.com at the destination. Different UPN, same person, no automatic resolution.
What Actually Works: A UPN Mapping Table
The pattern that works is boring: build a spreadsheet-shaped mapping of every source identity to its destination identity, hand it to the migration tool, and let the tool rewrite ACL entries at write-time. Two columns, one row per person.
🔑 The mapping table
| Source UPN | Destination UPN |
|---|---|
| jsmith@contoso.com | john.smith@fabrikam.com |
| arogers@contoso.com | alice.rogers@fabrikam.com |
| hr-team@contoso.com | hr@fabrikam.com |
| legal-review@contoso.com | legal.review@fabrikam.com |
The migration tool consumes this table at ACL-write time. Any source UPN not in the table is flagged, not silently dropped.
Where the mapping comes from
Most consultants build it once per project by joining the source tenant's user directory export with the destination tenant's HR list. In a consolidation (M&A) the HR side of the destination should know who's who because they onboarded the acquired staff. If you don't have that list yet, ask HR before starting the migration — not after.
Special cases the table needs to cover:
- Groups. Source groups and their destination equivalents map the same way. If the destination has already built the equivalent group structure, list source group UPN → destination group UPN. If not, map source group members to individuals.
- Terminated users. Users who left the company before the migration date should map to a designated fallback UPN (usually the department manager or a shared archive account). Don't leave them unmapped — the ACL entry disappears otherwise.
- External guests on source. If your source has invited third parties, the destination needs to re-invite them explicitly. The migration should flag these so you can decide per-person rather than mass-inviting.
How MigrationFox Handles This
MigrationFox's SharePoint connector accepts a permissionUserMappings array as part of the migration job options. Each entry is a sourceEmail → destEmail pair. At write time, when the connector encounters an ACL entry, it looks up the source UPN in the mapping and rewrites it to the destination UPN before writing.
What the wizard does
The New Migration wizard has a “Permission mapping” step when both source and destination are SharePoint. You can:
- Upload a CSV of the mapping table directly (columns:
sourceEmail,destEmail) - Enter individual mappings inline for small projects
- Skip the step — but the migration will produce a report listing every unresolved source UPN so you can review before repeating with a mapping
Any source UPN that isn't in the mapping table becomes a warning in the job log, not a silent drop. Post-migration, you get a report showing exactly which ACL entries were rewritten, which were flagged, and which were skipped — auditable end-to-end.
What’s preserved when the mapping matches
When both source and destination principals resolve, the ACL entry writes cleanly with the same permission level (Read / Contribute / Full Control / custom level). Item-level permissions, folder inheritance, and library-level default permissions all follow the same rewrite rule. If the destination tenant hasn’t provisioned the mapped user yet, the ACL will write successfully but access won’t work until the user account exists — provision first, migrate second.
True History mode + permissions
For same-tenant migrations, MigrationFox’s True History mode preserves the original Author, Created/Modified timestamps, and version history alongside permissions. Cross-tenant, True History still preserves timestamps and version history; permissions are rewritten via the mapping. Both are worth turning on for legal-hold-sensitive libraries.
Common Objections and Answers
"Can we just re-permission everything on the destination side after the migration finishes?"
You can, and lots of consultants do. It costs time you didn’t budget for — walking each user through re-applying access to the files they need — and it doesn’t preserve item-level permissions (private folders, restricted views). For large libraries the mapping-table approach is faster overall.
"Do we need to invite everyone as B2B guests?"
Only if the migrated users don’t already have accounts in the destination tenant. In a consolidation you’ve typically already provisioned them — use their new UPNs. In an outbound migration where the source users are leaving your directory entirely, guest invitations are appropriate but should happen before the migration runs.
"What about groups vs. individuals?"
Map groups where the destination has equivalent groups. Otherwise map to individuals. Trying to migrate a SharePoint permission from “hr-team@source.com” when the destination has no hr-team group and you haven’t mapped its members means the permission is functionally lost.
"How do we handle terminated users?"
Map them to a designated archive account (e.g. archive@destination.com) that’s a member of a security group with read-only access. The ACL entry still writes; access is preserved in principle; nobody who shouldn’t have data gets it.
Pre-Migration Checklist
Before scheduling the actual copy job:
- Build the mapping table. Export the source tenant users, cross-reference with destination HR list, resolve terminated users, resolve groups. Save as CSV with
sourceEmail,destEmailcolumns. - Run a dry-run on one library. A small library (100-500 files) is enough to surface mapping gaps. The report will list every unresolved source UPN.
- Update the mapping. Add rows for any UPN that came up unresolved. Iterate until the dry-run has zero unresolved.
- Provision destination users. Every UPN in the destination column must actually exist in the destination tenant before the ACLs write. Otherwise the permissions are pointing at ghosts.
- Run the full job. With a validated mapping, the real migration writes clean, resolvable ACLs at scale.
- Verify a sample. Log in as 3-5 destination users. Check they can open the files their source counterparts owned. Fix any gaps against the mapping and re-run for those items.
What This Saves You
The mapping-table approach turns a "we’ll deal with permissions after" recovery project into a build-once, apply-once, audit-once step. On a mid-size tenant migration (50k files, 500 users, 20 libraries), the mapping table takes a day to build; the alternative — re-permissioning by hand after the fact — typically takes weeks and leaves gaps.
Most importantly, the migration produces a clean audit trail. Every ACL rewrite is logged with source and destination UPN. Compliance teams can prove exactly what got mapped to what, when, and by whom. That’s the difference between "we migrated" and "we migrated defensibly."
Related Reading
- Cross-tenant SharePoint permissions — deeper technical dive
- SharePoint migration best practices for consultants
- SharePoint platform overview
Ready to migrate with permissions intact?
2 GB migration credits free on signup. Build your mapping table, run a dry-run library, then scale.
Start Free →