Field Notes · Sheet 01 / 30 · Identity and federation
Retiring AD FS with PowerShell
Two AD FS upgrades, one crash from a corrupted configuration, and about 30 relying parties moved to Entra ID, with PowerShell at every stage.
Bradley Baker · · 5 min read

Sheet 01 covers the end of AD FS in a 4,300-user global Microsoft 365 tenant: two farm upgrades between 2021 and 2025, one crash from a corrupted configuration, and about 30 relying parties moved to Entra ID. PowerShell did most of the work. This is the longer version, with the commands, the order they run in, and what Microsoft's documentation says about each step.
Two upgrades, three versions
The farm ran on two servers. It moved from Windows Server 2012 R2 to 2016, then to 2019, between January 2021 and October 2025.
Each version comes with a farm behavior level, a farm-wide setting that decides which features the farm can use. 2012 R2 is level 1, 2016 is level 3, and 2019 is level 4. A server running a newer version can join the farm, but the farm keeps running at the old level, in what Microsoft calls mixed mode, until you raise it. Raising the level also creates a new configuration database: AdfsConfigurationV3 at level 3 and AdfsConfigurationV4 at level 4.
Microsoft's upgrade guide lists prerequisites beyond the new servers themselves. The Active Directory schema has to be at level 85 or later for AD FS on Windows Server 2016, and 88 or later for 2019. The AD FS configuration and the federation servers need a backup. And the upgrade needs a planned end date, because a farm left in mixed mode for a long time can run into problems.
PowerShell
# The current level and the servers in the farm
Get-AdfsFarmInformation
# Remove each old server after uninstalling the AD FS role from it
Set-AdfsFarmInformation -RemoveNode "<old-server-FQDN>"
# Check, raise, and confirm
Test-AdfsFarmBehaviorLevelRaise
Invoke-AdfsFarmBehaviorLevelRaise
Get-AdfsFarmInformationThe crash came first
The farm also crashed once, from a corrupted configuration. Recovery came before any cutover work, for two reasons. Every relying party still signed in through the farm, and its configuration held the claim rules each app would need once it was rebuilt in Entra ID.
The second reason tied the recovery to the plan. The export in the next section reads trusts and claim rules from a working farm, so the retirement plan depended on the farm it was retiring.
Four stages, each in PowerShell
The retirement ran on PowerShell from start to finish, in four stages.
1. Inventory
Get-AdfsRelyingPartyTrust with no parameters returns every relying party trust in the farm. The export on the sheet keeps three properties for each one: its name, its identifiers, and its issuance transform rules.
PowerShell
Get-AdfsRelyingPartyTrust |
Select-Object Name, Identifier, IssuanceTransformRules |
Export-Clixml .\rp-trusts.xmlExport-Clixml writes the objects to a file that Import-Clixml can load again later. The claim rules come along as text, so the plan came from data instead of from clicking through the console.
2. Rebuild
Each app became an Entra enterprise app, built the same scripted way every time, and named business testers signed off on it.
Microsoft offers part of this in the admin center. Its AD FS application migration wizard creates the app registration and service principal, copies the identifier and reply URL, assigns the groups named in the trust's access control policy if they sync to Entra ID, and maps the claims Entra supports. It handles SAML apps only. It doesn't carry over the signing certificate or create Conditional Access policies, so those stay on the checklist either way.
3. Cutover
Sign-in activity on both sides showed when an app had really moved, and each cutover had a documented rollback path ready. Cutovers were planned around business hours, with application owners and user communication coordinated ahead of time.
On the Entra side, the evidence is the sign-in log for the new enterprise app. On the AD FS side, Microsoft's decommission guide points to the AD FS event logs and Microsoft Entra Connect Health, where any sign-in success or failure means something still depends on the farm.
A rebuilt app carries no traffic until the app itself is pointed at Entra ID. Microsoft's migration guide says the same about apps the wizard creates: the new app stays inactive until sign-in traffic is redirected to it, and rolling back before then means deleting it.
4. Decommission
Each trust came out only after its owner confirmed the app was stable and AD FS traffic for it had stopped. After the last relying party moved, the two-server farm was decommissioned.
For the farm itself, Microsoft's decommission guide asks for at least a week of Connect Health data on app usage in Entra ID, and no relying party traffic left on AD FS. Its steps then include, in order, an optional final backup, removing the load balancer and DNS entries, uninstalling the AD FS role starting with the secondary servers, deleting the SSL certificates, and re-imaging the servers.
Claim rules decide the effort
A trust that only needs a UPN is a rebuild. One with custom issuance rules or an external attribute store is a redesign. The AD FS application migration report in Entra flags those as Needs review or Additional steps required.
The report's rule checks show what makes a rule hard. These are the findings it raises on issuance rules, with what Entra offers instead.
| The AD FS rule | Report finding | In Entra ID |
|---|---|---|
| Matches a claim with a regular expression | UNSUPPORTED_CONDITION_PARAMETER | Transformations such as IfEmpty(), StartWith(), and Contains() |
| Rewrites a value with a regular expression | UNSUPPORTED_ISSUANCE_TRANSFORMATION | Transformations such as Extract(), Trim(), and ToLower() |
| Uses ADD to extend the incoming claim set | UNSUPPORTED_ISSUANCE_CLASS | Several claim transformations |
| Issues a restricted claim | RESTRICTED_CLAIM_ISSUED | Can be issued, but its source can't change and no transformation applies |
| Reads from an attribute store other than Active Directory | EXTERNAL_ATTRIBUTE_STORE | No equivalent. Entra sources claims only from Active Directory or Entra ID. |
Sheet 03 turns this into eight questions asked of every relying party before it moves. Questions 3 and 4 there are the claim-rule questions.
If you still run AD FS
Start with the question the post ended on: how many of your relying parties had a sign-in in the last 30 days? With the Connect Health agent for AD FS installed, the migration report answers it. The report lists only apps with sign-ins in that window and leaves out Microsoft relying parties such as Office 365, so an app missing from it is either idle or one of Microsoft's.
Then run the export. The plan for this retirement came from that file, not from the console.
Sources
- Upgrade an existing AD FS farm by using Windows Internal Databaselearn.microsoft.com
- Get-AdfsRelyingPartyTrustlearn.microsoft.com
- AD FS application migration to move AD FS apps to Microsoft Entra IDlearn.microsoft.com
- Active Directory Federation Services (AD FS) decommission guidelearn.microsoft.com
From the field reports
- AD FS
- Entra ID
- PowerShell
- SAML 2.0
- Migration