In this section

MSA1.5 Hybrid Identity — What Breaks and What's Legacy

8 hours · Module 1 · Free
What you already know

You've designed the hybrid identity architecture in MSA1.4 — Cloud Sync with PHS for NE. This sub addresses what most hybrid environments also contain: legacy components that were deployed during an earlier migration phase and never fully decommissioned. AD FS farms, Seamless SSO, PTA agents, old sync servers, deprecated PowerShell modules, legacy MFA policies. Each was correct when deployed. Many no longer serve a purpose. Some are actively creating security risk because their attack surface persists after their function was replaced. The architectural discipline is knowing what to identify, what to retire, in what order, and what breaks during each transition.

Hybrid identity environments accumulate legacy components like geological strata — each layer deposited during a different migration phase, each one still present even after its replacement was deployed. An AD FS farm from 2018 because federation was the only option. PTA agents installed because the migration guide recommended them alongside Entra Connect. Seamless SSO configured to smooth the user experience during transition. Legacy PowerShell modules embedded in automation scripts. Per-user MFA policies that pre-date Conditional Access. Each component was deployed for a valid reason. Many of those reasons no longer apply. Some of these components are deprecated, some are retired, and some are actively creating security risk by providing attack surface that serves no defensive purpose. This sub teaches you to identify, assess, and retire every legacy hybrid identity component.

Estimated time: 45 minutes.

AD FS — the Golden SAML attack surface

Active Directory Federation Services was the original hybrid authentication method. Before Password Hash Sync and Pass-Through Authentication existed, AD FS was the only way for on-premises users to authenticate against cloud services like M365. At its peak deployment (roughly 2015–2020), AD FS was Microsoft's recommended approach for enterprise M365 environments.

How AD FS works architecturally

AD FS functions as a Security Token Service (STS) — an on-premises identity provider that issues digitally signed SAML or WS-Federation tokens. The authentication flow works in four steps:

A user tries to access a cloud application (M365, AWS, Salesforce — any service with a federated trust). The cloud application redirects the user's browser to the organization's AD FS server. AD FS authenticates the user against on-premises Active Directory (via Kerberos or forms-based authentication), evaluates its claims pipeline (which maps AD attributes to SAML claims), and creates a SAML assertion describing the user's identity and entitlements. AD FS digitally signs this assertion using its token-signing certificate's private key. The signed assertion is sent back to the cloud application, which validates the signature against the public key it received during the federation trust configuration, and grants access.

The critical security assumption: the cloud application trusts the SAML assertion because it's signed with a private key that only AD FS possesses. If anyone else obtains that private key, they can sign their own assertions — and every federated application will accept them.

The Golden SAML attack

Golden SAML is the identity equivalent of a Golden Ticket in Kerberos. An attacker who obtains the AD FS token-signing certificate's private key can forge SAML assertions for any user, with any claims, to any federated application — bypassing passwords, MFA, Conditional Access, and all other authentication controls.

The attack was first described by CyberArk in 2017 and gained global attention when it was used in the SolarWinds supply chain attack (2020–2021), where the threat actor (attributed to Russia's SVR) compromised targets' AD FS servers to forge SAML tokens for persistent access to M365 and Azure environments. Microsoft's own blog on the topic describes the attack mechanics: "stealing a federation server's private key to forge correctly signed tokens to access its relying parties is the essence of the Golden SAML attack."

The attacker needs two pieces of cryptographic material from the AD FS server. The first is the encrypted token-signing certificate, stored in AD FS's configuration database (Windows Internal Database or SQL Server). The second is the Distributed Key Management (DKM) master key, stored in Active Directory, which decrypts the token-signing certificate. With both pieces, the attacker can decrypt the certificate, extract the private key, and use tools like Mandiant's ADFSpoof to build and sign arbitrary SAML assertions offline — from any machine, at any time, without touching the AD FS server again.

The attack is devastating because of three properties:

Persistence. As long as the stolen token-signing certificate remains valid (certificates are typically valid for 1–3 years, and many organizations don't rotate them), the attacker has persistent access. Changing user passwords doesn't stop it — the password is never used in the forgery process. Resetting MFA doesn't stop it — MFA is bypassed entirely. Revoking sessions doesn't stop it — the attacker generates a new forged token.

Stealth. The forged assertion is indistinguishable from a legitimate one because it's signed with the real private key. Standard sign-in logs show a successful federation authentication — they don't flag the assertion as forged. Detection requires correlating the cloud sign-in event with on-premises AD FS authentication events (Event IDs 1200 and 1202) — if the cloud login occurred but no corresponding on-premises authentication event exists, the assertion was likely forged. Few organizations have this cross-correlation in place.

Scope. A single token-signing certificate signs assertions for every federated application. An attacker who steals the AD FS certificate can access M365, AWS, Azure, Salesforce, and every other SAML-federated application in the organization's trust relationships — with any user identity, including Global Administrator.

Why decommissioning AD FS eliminates the risk

Microsoft's countermeasure guidance is direct: "the most effective countermeasure for Golden SAML attacks against your on-premises federation servers is to avoid maintaining federation servers that require you to manage your own SAML signing certificates at all." In other words: migrate from AD FS to cloud authentication (PHS or CBA) and decommission the AD FS farm. When there's no AD FS server, there's no token-signing certificate to steal, and Golden SAML is not possible.

The migration path is structured:

Step 1 — Inventory relying party trusts. Every application that authenticates through AD FS has a Relying Party Trust. Use Microsoft's AD FS application migration tool to identify which applications can be migrated to Entra ID (as enterprise applications with SAML or OIDC) and which need manual reconfiguration.

Step 2 — Enable staged rollout. Before converting the domain, test cloud authentication with specific security groups using staged rollout. Users in the staged groups authenticate against Entra ID (PHS). Users outside the groups continue authenticating through AD FS. This lets you validate cloud authentication works for your environment without committing the entire domain.

Step 3 — Convert the domain from Federated to Managed. Check the current state:

$domain = Get-MgDomain -DomainId "yourtenant.onmicrosoft.com"
$domain | Select-Object Id, AuthenticationType, IsVerified
Id                 AuthenticationType  IsVerified
--                 ------------------  ----------
yourtenant.onmicrosoft.com   Managed             True

AuthenticationType: Managed confirms the organization's domain is already using cloud authentication. If this showed Federated, the domain would still route authentication through AD FS, and the conversion would be the critical step.

Entra Admin Center

IdentitySettingsDomain names → select your domain
The Authentication type column shows Managed or Federated. If Federated, the federation metadata URL and passive sign-on URI are also displayed.

Step 4 — Decommission. After all applications are migrated and the domain is managed: remove the AD FS and WAP servers from the domain, disable the AD FS service account, remove DNS records for the AD FS farm, remove the certificate from the certificate store, and delete the DKM container from AD if it's no longer needed. Each step should be verified:

# Verify no federation trust exists
$federationConfig = Invoke-MgGraphRequest -Method GET `
  -Uri "https://graph.microsoft.com/v1.0/domains/yourtenant.onmicrosoft.com/federationConfiguration"
# Empty result = no federation configured

NE never deployed AD FS — they migrated directly from Entra Connect with PHS. But this section is included because many organizations reading this course inherited AD FS from a previous migration, and Golden SAML is one of the most severe identity attacks in the threat landscape. If you have AD FS, decommissioning it is the single highest-impact legacy cleanup you can do.

Seamless SSO — the AZUREADSSOACC attack surface

Seamless SSO was designed to provide transparent single sign-on for users on domain-joined devices connected to the corporate network. Understanding how it works mechanically explains why it's an attack surface.

How Seamless SSO works

When Seamless SSO is configured, the setup wizard creates a computer account named AZUREADSSOACC in on-premises Active Directory. This account has a Kerberos decryption key — essentially a shared secret between on-premises AD and Entra ID. When a user on a domain-joined device tries to access a cloud resource:

The user's browser sends the authentication request to Entra ID. Entra ID detects that Seamless SSO is enabled and returns a challenge that the user's device can resolve using Kerberos. The user's device requests a Kerberos service ticket for the AZUREADSSOACC account from the domain controller. The DC issues the ticket (the user is already authenticated to the domain via Kerberos). The device sends this Kerberos ticket to Entra ID. Entra ID decrypts the ticket using the AZUREADSSOACC key it has stored, validates the user's identity from the ticket, and issues an OAuth token. The user is signed in without entering credentials.

The user experience is seamless — no password prompt, no MFA prompt (unless CA policy requires it for the specific application). The mechanism is elegant. The security problem is the AZUREADSSOACC key.

Why the key is an attack surface

The AZUREADSSOACC computer account's Kerberos key is the shared secret that makes Seamless SSO work. If an attacker extracts this key (via DCSync, direct access to the AD database, or by compromising the computer account object), they can forge Kerberos tickets that Entra ID will accept — a "Silver Ticket" for cloud SSO. The forged ticket allows the attacker to authenticate as any domain user to Entra ID without knowing the user's password.

Microsoft recommends rotating the AZUREADSSOACC key every 30 days. In practice, most organizations never configure the rotation. Let's check NE:

# Run on a domain-joined server with AD PowerShell module
$ssoAccount = Get-ADComputer -Filter "Name -eq 'AZUREADSSOACC'" `
  -Properties PasswordLastSet, Enabled, WhenCreated, Description
if ($ssoAccount) {
  $keyAge = ((Get-Date) - $ssoAccount.PasswordLastSet).Days
  Write-Host "AZUREADSSOACC found"
  Write-Host "  Created:      $($ssoAccount.WhenCreated)"
  Write-Host "  Key last set: $($ssoAccount.PasswordLastSet)"
  Write-Host "  Key age:      $keyAge days (recommended: ≤30)"
  Write-Host "  Enabled:      $($ssoAccount.Enabled)"
} else {
  Write-Host "AZUREADSSOACC not found — Seamless SSO was not configured"
}
AZUREADSSOACC found
  Created:      2022-09-14T11:22:33Z
  Key last set: 2024-03-22T14:33:11Z
  Key age:      410 days (recommended: ≤30)
  Enabled:      True

The AZUREADSSOACC account exists, was created in September 2022 (when NE originally configured Entra Connect), the key was last rotated in March 2024 (410 days ago — 13 times the recommended maximum), and the account is still enabled. This is an active attack surface that serves no purpose. NE migrated to Cloud Sync, which doesn't use Seamless SSO. The AZUREADSSOACC account should be disabled and eventually deleted.

Entra Admin Center

IdentityHybrid managementMicrosoft Entra ConnectConnect Sync
The Seamless single sign-on card shows Enabled or Disabled and lists the on-premises AD domains it's configured for.

Note: The AZUREADSSOACC key age and rotation status are only visible in on-premises Active Directory (Active Directory Users and Computers → Computers container) or via the PowerShell query above. The portal shows the feature status but not the credential health.

Disable and clean up the account:

# Step 1 — Disable the computer account (stops Kerberos ticket issuance)
Set-ADComputer -Identity "AZUREADSSOACC" -Enabled $false
Write-Host "AZUREADSSOACC disabled"

# Step 2 — Verify no Seamless SSO sign-ins occurred recently
#          (if sign-ins exist, something is still using it — investigate)
$ssoSignIns = Get-MgAuditLogSignIn -Filter `
  "authenticationDetails/any(a: a/authenticationMethod eq 'Seamless SSO')" `
  -Top 10
if ($ssoSignIns.Count -eq 0) {
  Write-Host "No Seamless SSO sign-ins found — safe to proceed"
} else {
  Write-Host "WARNING: $($ssoSignIns.Count) Seamless SSO sign-ins found — investigate before deleting"
}

# Step 3 — Delete the computer account (only after confirming no usage)
# Remove-ADComputer -Identity "AZUREADSSOACC" -Confirm:$false

# Step 4 — Verify the account is gone
$check = Get-ADComputer -Filter "Name -eq 'AZUREADSSOACC'" -ErrorAction SilentlyContinue
if (-not $check) {
  Write-Host "AZUREADSSOACC removed from Active Directory"
} else {
  Write-Host "Account still exists — verify removal"
}

Step 3 is commented out deliberately. Disable first (Step 1), wait 48 hours, confirm no authentication failures or help desk tickets, then delete. Deleting an account that something still depends on causes an outage. Disabling it causes a detectable failure that you can reverse.

What replaces Seamless SSO

Two modern mechanisms provide SSO without the AZUREADSSOACC account:

Primary Refresh Token (PRT). For Entra joined and hybrid Entra joined devices, the device obtains a PRT during sign-in. The PRT provides SSO to all cloud applications — the user signs into Windows once, and the PRT handles subsequent cloud authentication transparently. No AZUREADSSOACC account, no Kerberos dependency for cloud SSO.

Cloud Kerberos Trust. For organizations that need SSO to on-premises Kerberos resources (file shares, on-premises web applications) from users authenticating with passwordless methods (FIDO2, Windows Hello), Cloud Kerberos Trust provides a mechanism that doesn't require an on-premises AZUREADSSOACC account or AD FS. It's configurable via the cloudKerberosTrustEnabled sync feature flag (currently OFF in the organization's configuration — a consideration for MSA2 when designing passwordless authentication).

The stale sync server — the organization's specific legacy risk

MSA1.4 identified that the organization's legacy Entra Connect server was powered off but not decommissioned. Let's enumerate every residual risk component and build the decommission verification sequence.

Five specific assets create residual risk:

  1. The server's computer account in AD — allows the server to authenticate to the domain if powered on
  2. The Entra Connect service account in AD — has read access to all AD objects (and write access if password writeback was configured on the old server)
  3. The Entra Connect service account in Entra ID — member of the Directory Synchronization Accounts role, which grants write permissions to user, group, and contact objects
  4. The SQL LocalDB database on the server's disk — contains the sync configuration, connector spaces, and potentially cached credential material
  5. The Entra Connect application registration in Entra ID — the service principal that the old installation used to authenticate to the Graph API

Query the status of each:

# Check for the legacy service principal in Entra ID
$legacyConnect = Get-MgServicePrincipal `
  -Filter "displayName eq 'Microsoft Azure AD Connect'" `
  -Property DisplayName, AppId, AccountEnabled
if ($legacyConnect) {
  Write-Host "Legacy Entra Connect service principal found"
  Write-Host "  AppId:   $($legacyConnect.AppId)"
  Write-Host "  Enabled: $($legacyConnect.AccountEnabled)"
} else {
  Write-Host "No legacy Connect service principal — clean"
}

# Check Directory Synchronization Accounts role membership
$syncRole = Get-MgDirectoryRole `
  -Filter "displayName eq 'Directory Synchronization Accounts'"
if ($syncRole) {
  $members = Get-MgDirectoryRoleMember -DirectoryRoleId $syncRole.Id
  Write-Host "Directory Sync Accounts role members: $($members.Count)"
  $members | ForEach-Object {
    $type = $_.AdditionalProperties['@odata.type']
    $name = $_.AdditionalProperties['displayName']
    Write-Host "  $name ($type)"
  }
}

Entra Admin Center

Check the legacy service principal:
IdentityApplicationsEnterprise applications → search for "Microsoft Azure AD Connect"
If found, the application's Properties page shows the enabled/disabled status.

Check Directory Sync role membership:
IdentityRoles & admins → search for "Directory Synchronization Accounts" → click the role → Active assignments
Shows all current members. To remove a member, select them and click Remove.

The decommission sequence — full implementation with verification:

Step 1 — Confirm Cloud Sync is healthy before touching anything:

$org = Get-MgOrganization
$syncAge = ((Get-Date).ToUniversalTime() - $org.OnPremisesLastSyncDateTime).TotalMinutes
$syncedCount = (Get-MgUser -All -Filter "onPremisesSyncEnabled eq true" `
  -ConsistencyLevel eventual -CountVariable c).Count

Write-Host "Sync status: $($org.OnPremisesSyncEnabled)"
Write-Host "Last sync:   $($org.OnPremisesLastSyncDateTime) ($([int]$syncAge) min ago)"
Write-Host "Synced users: $syncedCount"

if ($syncAge -gt 10 -or $syncedCount -lt 700) {
  Write-Host "WARNING: Sync may not be healthy. Do NOT proceed until resolved." -ForegroundColor Red
} else {
  Write-Host "Sync healthy — proceed with decommission" -ForegroundColor Green
}

Step 2 — Remove the legacy service account from the Directory Sync Accounts role:

# Identify the legacy service account in the role
$syncRole = Get-MgDirectoryRole -Filter "displayName eq 'Directory Synchronization Accounts'"
$roleMembers = Get-MgDirectoryRoleMember -DirectoryRoleId $syncRole.Id
$roleMembers | ForEach-Object {
  $name = $_.AdditionalProperties['displayName']
  Write-Host "Role member: $name (ID: $($_.Id))"
}

# Remove the legacy service account (replace with the actual ID)
# Confirm this is the OLD account, not the current Cloud Sync account
$legacyAccountId = "ID-of-legacy-connect-service-account"
Remove-MgDirectoryRoleMemberByRef `
  -DirectoryRoleId $syncRole.Id `
  -DirectoryObjectId $legacyAccountId

Write-Host "Removed legacy account from Directory Sync role"

Step 3 — Wait 10 minutes, then verify Cloud Sync still works:

Start-Sleep -Seconds 600  # Wait 10 minutes

$org = Get-MgOrganization
$newSyncAge = ((Get-Date).ToUniversalTime() - $org.OnPremisesLastSyncDateTime).TotalMinutes
Write-Host "Post-removal sync check:"
Write-Host "  Last sync: $($org.OnPremisesLastSyncDateTime) ($([int]$newSyncAge) min ago)"

if ($newSyncAge -lt 10) {
  Write-Host "  Cloud Sync is still working — safe to continue" -ForegroundColor Green
} else {
  Write-Host "  WARNING: Sync may have stopped. Investigate before proceeding." -ForegroundColor Red
  Write-Host "  If sync broke, re-add the account: New-MgDirectoryRoleMemberByRef"
}

Step 4 — Disable the legacy service account in on-premises AD:

# Run on a domain controller or domain-joined server with AD module
$legacySvcAccount = Get-ADUser -Filter "SamAccountName -eq 'MSOL_abc123def'" `
  -Properties Enabled, LastLogonDate
Write-Host "Legacy service account: $($legacySvcAccount.SamAccountName)"
Write-Host "  Enabled:     $($legacySvcAccount.Enabled)"
Write-Host "  Last logon:  $($legacySvcAccount.LastLogonDate)"

# Disable the account
Set-ADUser -Identity $legacySvcAccount -Enabled $false
Write-Host "Account disabled in AD"

# Verify
(Get-ADUser -Identity $legacySvcAccount -Properties Enabled).Enabled
# Expected: False

Step 5 — Disable AZUREADSSOACC (if present — already covered above).

Step 6 — Remove the legacy server from the domain:

# On the legacy server itself (if accessible):
Remove-Computer -Force -Restart

# If the server is inaccessible, remove its AD computer account:
$legacyServer = Get-ADComputer -Filter "Name -eq 'NE-AADC01'" -Properties OperatingSystem
Write-Host "Server: $($legacyServer.Name)"
Write-Host "OS:     $($legacyServer.OperatingSystem)"

# Remove from domain (the computer object in AD)
Remove-ADComputer -Identity $legacyServer -Confirm:$false
Write-Host "Computer account removed from AD"

Steps 7–8 — Wipe the server disk and remove DNS records: These are physical/infrastructure tasks. The SQL LocalDB database on the server's disk contains the sync configuration, connector spaces, and cached identity data. If the disk is accessible (not encrypted with BitLocker, or recoverable), it should be wiped or physically destroyed. Remove any A records, CNAME records, or SRV records in DNS that pointed to the legacy server.

Step 9 — Document completion:

# Final verification — the legacy footprint should be zero
$legacyConnect = Get-MgServicePrincipal `
  -Filter "displayName eq 'Microsoft Azure AD Connect'"
$ssoAccount = Get-ADComputer -Filter "Name -eq 'AZUREADSSOACC'" -ErrorAction SilentlyContinue
$legacySvc = Get-ADUser -Filter "SamAccountName -eq 'MSOL_abc123def'" `
  -Properties Enabled -ErrorAction SilentlyContinue
$legacyServer = Get-ADComputer -Filter "Name -eq 'NE-AADC01'" -ErrorAction SilentlyContinue

Write-Host "=== Legacy Footprint Check ==="
Write-Host "Connect SP:       $(if($legacyConnect){'EXISTS — investigate'}else{'Clean'})"
Write-Host "AZUREADSSOACC:    $(if($ssoAccount){'EXISTS — disable/remove'}else{'Clean'})"
Write-Host "Legacy svc acct:  $(if($legacySvc -and $legacySvc.Enabled){'ENABLED — disable'}
                                elseif($legacySvc){'Disabled — consider removal'}else{'Clean'})"
Write-Host "Legacy server:    $(if($legacyServer){'EXISTS — remove'}else{'Clean'})"

Update ADR-MSA1-002 with the decommission completion date. Close risk register entries MSA1-RISK-002 and MSA1-RISK-003.

The verification between steps 2 and 4 is critical. Disabling the Entra ID role membership first (step 2) ensures that if the legacy server were powered on, it can't write to Entra ID. Waiting and verifying Cloud Sync continues (step 3) confirms the legacy account wasn't being used by the current infrastructure. Then disabling the on-premises account (step 4) closes the on-premises side. This order ensures you don't break the working sync while removing the stale one.

Legacy PowerShell modules

The AzureAD, AzureAD-Preview, and MSOnline (MSOL) PowerShell modules were deprecated in March 2024 and retired in October 2025. These modules no longer function — any script calling Get-AzureADUser, Set-AzureADUser, Get-MsolUser, or Connect-AzureAD fails with authentication errors.

The replacement is the Microsoft Graph PowerShell module (Microsoft.Graph), which this course uses throughout. The migration isn't trivial — some cmdlets have direct Graph equivalents, others require different approaches. Licence management, for example, moved from Set-MsolUserLicense to Set-MgUserLicense with a different parameter structure. Group-based operations, report generation, and bulk user management all have different patterns in Graph PowerShell.

The architectural concern isn't the modules (they're broken). It's the automation that depended on them. Many organizations have:

  • Scheduled tasks on servers that run AzureAD/MSOL scripts for user provisioning, license assignment, or reporting
  • Azure Automation runbooks that call deprecated cmdlets
  • IT service management workflows that invoke PowerShell for identity operations
  • Monitoring scripts that use MSOL to check for configuration drift

When the modules stopped working in October 2025, some scripts failed loudly (error emails, visible failures). Others failed silently — a reporting script that returns empty results instead of erroring, a provisioning script that skips the license assignment step because Set-MsolUserLicense returned an error that was caught and suppressed. Silent failures are worse because the process appears to work while actually doing nothing.

Audit for legacy module references:

# Search common automation locations for legacy module usage
$paths = @("C:\Scripts", "C:\Automation", "D:\Scheduled")
foreach ($path in $paths) {
  if (Test-Path $path) {
    $matches = Get-ChildItem -Path $path -Recurse -Include "*.ps1","*.psm1" |
      Select-String -Pattern "AzureAD|Get-Msol|Set-Msol|Connect-AzureAD|Connect-MsolService"
    if ($matches) {
      Write-Host "Legacy references in $path :"
      $matches | Select-Object Path, LineNumber, Line | Format-Table -AutoSize
    }
  }
}

Additionally, earlier versions of Entra Connect Sync used the MSOnline module internally when running the installation wizard. If you're still running Entra Connect Sync (the tenant has migrated to Cloud Sync, but organizations that haven't), version 2.5.79.0 or later is required by September 30, 2026 — older versions will fail when Microsoft completes the back-end service change that removes MSOnline dependencies from the sync protocol.

Legacy MFA and SSPR policies

Before the unified Authentication Methods Policy, MFA and SSPR were configured through two separate legacy interfaces. Per-user MFA was managed at account.activedirectory.windowsazure.com — an admin individually toggled MFA to "Enabled" or "Enforced" for each user. SSPR had its own separate policy configuration. These interfaces were retired on September 30, 2025.

The architectural problem with per-user MFA is that it operates outside the Conditional Access framework. A user with per-user MFA set to "Enforced" is always prompted for MFA — regardless of what CA policies say. This creates unpredictable behavior. A CA policy that says "require MFA only for risky sign-ins" is overridden by the per-user setting. A CA policy that says "require phishing-resistant MFA" is satisfied by any MFA method because per-user MFA accepts all registered methods.

The target state is all MFA enforcement through Conditional Access policies (MSA3) — giving the architect full control over who is prompted, under what conditions, and which authentication methods satisfy the requirement. No per-user MFA. No Security Defaults. No legacy SSPR policies.

Check the Authentication Methods Policy status:

$authPolicy = Invoke-MgGraphRequest -Method GET `
  -Uri "https://graph.microsoft.com/v1.0/policies/authenticationMethodsPolicy"

# Check migration status
Write-Host "Policy state: $($authPolicy.policyMigrationState)"
Write-Host "Registration campaign state: $($authPolicy.registrationEnforcement.authenticationMethodsRegistrationCampaign.state)"
Write-Host ""

# List enabled authentication methods
$authPolicy.authenticationMethodConfigurations | ForEach-Object {
  Write-Host "$($_.id): $($_.state)"
}
Policy state: migrationComplete
Registration campaign state: enabled

fido2: enabled
microsoftAuthenticator: enabled
sms: enabled
temporaryAccessPass: enabled
email: disabled
voice: disabled
x509Certificate: disabled
softwareOath: enabled

policyMigrationState: migrationComplete means the tenant has migrated from the legacy MFA/SSPR interfaces to the unified Authentication Methods Policy. The enabled methods (FIDO2, Authenticator, SMS, TAP, software OATH) are the methods users can register and use. Note that SMS is still enabled — MSA2 addresses whether SMS should remain as an allowed authentication method given its susceptibility to SIM swapping and interception.

Entra Admin Center

Authentication methods overview:
ProtectionAuthentication methodsPolicies
Shows every authentication method with its current state (Enabled/Disabled), target groups, and configuration details.

Migration status:
ProtectionAuthentication methodsActivityMigration status
Confirms whether legacy MFA/SSPR policies have been migrated to the unified policy.

Per-method configuration:
Click any method (FIDO2 security keys, Microsoft Authenticator, SMS, Temporary Access Pass, etc.) to enable/disable it, set target groups (all users vs specific groups), and configure method-specific settings (FIDO2 key restrictions, Authenticator number matching, etc.). This is the primary interface for MSA2's authentication architecture design.

the organization's legacy component inventory

Component                Status           Risk     Action
-----------------------  ---------------  -------  ----------------------------------
AD FS                    Never deployed   None     N/A

Seamless SSO             AZUREADSSOACC    HIGH     Disable account immediately.
(AZUREADSSOACC)          exists, key 410  (stale   Key age 410 days (recommended 30).
                         days old,        Kerberos Serves no purpose with Cloud Sync.
                         account enabled  key)

Legacy Entra Connect     Server powered   HIGH     Execute 9-step decommission
server                   off, not decomm  (Tier 0  sequence. Verify Cloud Sync
                                          creds)   health between steps.

Legacy service account   Exists in AD +   HIGH     Remove from Directory Sync
(Connect)                Entra ID, may    (dir     Accounts role. Disable in both
                         have dir sync    sync     directories. Verify Cloud Sync
                         role             perms)   unaffected.

Legacy PowerShell        Modules retired  MEDIUM   Audit all automation scripts.
(AzureAD/MSOL)           Oct 2025         (silent  Migrate to Microsoft.Graph.
                                          fails)   Test each migrated script.

Per-user MFA settings    Migration        LOW      Verify policyMigrationState =
                         complete                  migrationComplete. Confirm all
                                                   MFA via CA (MSA3).

Entra Connect Sync       N/A (migrated    None     N/A — NE uses Cloud Sync.
version deadline         to Cloud Sync)
(Sep 2026)

SMS as auth method       Enabled in       MEDIUM   Evaluate in MSA2 whether SMS
                         AuthMethods              should remain. SIM swap risk.
                         Policy

Three HIGH-risk items require immediate action. The AZUREADSSOACC account and the legacy Entra Connect server/service account are MSA1.11 risk register entries. The Seamless SSO account is the quickest fix — one PowerShell command to disable it. The server decommission is a 9-step sequence that should be scheduled as a maintenance window.

Before moving on, verify your understanding: Describe the Golden SAML attack in five steps: what the attacker compromises, what they steal (two specific cryptographic materials), how they forge the token, and why password resets don't stop the attack. Explain how Seamless SSO works mechanically — name the specific AD computer account involved, describe the Kerberos flow, and explain what an attacker who extracts the account's key can do.


Reusable script — the commands from this sub assembled for operational use:

Copy the NE legacy component inventory into your architecture package at 01-identity/legacy-inventory.md. For each HIGH-risk component, create a risk register entry at risk-register/ne-risk-register.md with:

  • MSA1-RISK-001: AZUREADSSOACC account — 410-day-old key, enabled, serves no purpose
  • MSA1-RISK-002: Legacy Entra Connect service account — directory sync permissions active
  • MSA1-RISK-003: Legacy Entra Connect server — powered off, not decommissioned

For your own environment, run the verification queries:

# Domain authentication type (Federated = AD FS still active)
(Get-MgDomain -DomainId "yourdomain.com").AuthenticationType

# Seamless SSO account (run on domain controller)
Get-ADComputer -Filter "Name -eq 'AZUREADSSOACC'" -Properties PasswordLastSet

# Legacy Entra Connect service principal
Get-MgServicePrincipal -Filter "displayName eq 'Microsoft Azure AD Connect'"

# Authentication Methods Policy migration state
(Invoke-MgGraphRequest -Method GET `
  -Uri "https://graph.microsoft.com/v1.0/policies/authenticationMethodsPolicy"
).policyMigrationState
Next

MSA1.6 — Directory Structure and Administrative Units. You've cleaned up the legacy components. MSA1.6 teaches the internal structure of the directory — Administrative Units as delegated administration boundaries that limit the blast radius of every admin action. the organization's flat directory (all admins with tenant-wide scope) is an architectural problem, and AUs are the mechanism for fixing it.

You're reading the free modules of m365-security-architecture

The full course continues with advanced topics, production detection rules, worked investigation scenarios, and deployable artifacts.

View Pricing See Full Syllabus