Fusionar usuarios de AD con Entra ID en entorno híbrido: soft match y hard match para resolver ProxyAddresses duplicados

Guía práctica y completa para unir identidades de Active Directory local con Entra ID (Azure AD) en un entorno híbrido cuando aparecen conflictos de ProxyAddresses. Incluye preparación, soft match y hard match con Microsoft Graph, verificación y solución de los casos que “se resisten”.

Índice

Escenario y objetivo

Quieres habilitar un entorno híbrido (AD local + Entra ID) con inicio de sesión único entre Exchange on‑premises y Microsoft 365. Los usuarios que existen solo en AD local se sincronizan bien mediante Azure AD Connect, pero aquellos que ya existen en la nube con el mismo correo electrónico fallan con error de ProxyAddresses duplicados. Tras habilitar la coincidencia por UPN (soft match on UPN) los objetos nuevos se unen, pero queda al menos un usuario que no logra fusionarse.

Resumen técnico de la causa

Azure AD Connect intenta unir el objeto local con el objeto de la nube. Si las reglas de coincidencia no consiguen emparejarlos, el servicio percibe el mismo SMTP primario en dos objetos distintos y dispara un conflicto de ProxyAddresses. El resultado es un intento fallido de unión que hay que resolver manualmente.

Conceptos clave

Join (unión) Operación de Azure AD Connect por la que un objeto de AD local se empareja con el objeto ya existente en Entra ID, convirtiéndolo en “sincronizado”. Soft match Coincidencia no forzada. Por defecto, usa proxyAddresses (SMTP primario); si habilitas la característica, también podrá emparejar por UPN. Hard match Coincidencia forzada estableciendo OnPremisesImmutableId del usuario en la nube con el valor del anchor de AD (recomendado: mS-DS-ConsistencyGuid). Anchor (sourceAnchor) Identificador inmutable que relaciona de forma única el objeto local y el de la nube. En implementaciones modernas es mS-DS-ConsistencyGuid; si no existe, se usa objectGUID.

Preparación esencial antes de cualquier intento

Estas acciones previas reducen en gran medida los conflictos y aceleran la unión.

Alinear atributos en AD local y en la nube

  • UPN: el userPrincipalName del usuario en AD local debe coincidir con el UPN del usuario en Entra ID.
  • SMTP primario: en proxyAddresses, el valor SMTP:usuario@dominio (etiqueta en mayúsculas para indicar primario) debe ser idéntico al del objeto en la nube.

Comandos útiles en AD local

# En un DC o equipo con RSAT y el módulo ActiveDirectory
Get-ADUser -Identity "jgomez" -Properties userPrincipalName,mail,proxyAddresses,'mS-DS-ConsistencyGuid','ObjectGUID' |
 Select-Object SamAccountName,userPrincipalName,mail,
 @{n='PrimarySMTP';e={($.proxyAddresses | Where-Object {$ -cmatch '^SMTP:'}) -replace '^SMTP:'}},
 @{n='AllProxies';e={$_.proxyAddresses -join ';'}},
 @{n='ConsistencyGuid';e={if($.'mS-DS-ConsistencyGuid'){[Guid]$.'mS-DS-ConsistencyGuid'} else {$null}}},
 ObjectGUID

Comandos útiles en la nube (Graph)

Install-Module Microsoft.Graph -Scope CurrentUser
Connect-MgGraph -Scopes User.Read.All
Get-MgUser -UserId "usuario@dominio.com" -Property userPrincipalName,mail,proxyAddresses,onPremisesImmutableId,onPremisesSyncEnabled,onPremisesLastSyncDateTime |
 Select-Object userPrincipalName,mail,onPremisesImmutableId,onPremisesSyncEnabled,onPremisesLastSyncDateTime,
 @{n='PrimarySMTP';e={($.proxyAddresses | Where-Object {$ -cmatch '^SMTP:'}) -replace '^SMTP:'}}

Eliminar duplicados reales de direcciones SMTP en la nube

Asegúrate de que ninguna otra entidad de Exchange Online (usuario, buzón compartido, recurso, contacto, grupo) —incluidos los elementos eliminados recientemente— tiene la misma dirección SMTP.

# Módulo de Exchange Online (V3)
Connect-ExchangeOnline
$addr = "usuario@dominio.com"
Get-Recipient -ResultSize Unlimited -IncludeSoftDeletedRecipients -Filter "EmailAddresses -eq 'smtp:$addr'" |
 Select-Object Name,RecipientType,PrimarySmtpAddress

Si aparece más de un objeto con esa dirección, corrige el que no corresponda (por ejemplo, cambia o quita el alias en el objeto incorrecto) antes de seguir.

Sincronizaciones a mano

# Ejecutar sincronización con Azure AD Connect
Start-ADSyncSyncCycle -PolicyType Delta     # Cambios incrementales
Start-ADSyncSyncCycle -PolicyType Initial   # Recalcular todo (si cambiaste reglas/ámbitos)

Recomendación: ejecuta IdFix en AD antes de migraciones masivas para detectar UPNs no válidos, proxyAddresses duplicados o caracteres ilegales.

Opción rápida: soft match por UPN

Úsala cuando aún no has intentado unir ese usuario y los atributos ya están alineados. Habilita la coincidencia por UPN y ejecuta una sincronización.

# Característica de coincidencia por UPN (MSOnline; legado)
Install-Module MSOnline -Scope CurrentUser
Connect-MsolService
Set-MsolDirSyncFeature -Feature EnableSoftMatchOnUpn -Enable $true
Start-ADSyncSyncCycle -PolicyType Delta

Esta vía es ideal para nuevos objetos o para OUs recién incorporadas al ámbito de sincronización. Si el usuario ya registró intentos fallidos, avanza a hard match.

Nota: el módulo MSOnline está en desuso. Para escenarios problemáticos y automatizaciones futuras, estandariza en Microsoft Graph.

Opción recomendable: hard match con Microsoft Graph

Forzar la unión establece el OnPremisesImmutableId en el usuario de la nube con el valor del anchor del objeto local (idealmente mS-DS-ConsistencyGuid; si no existe, objectGUID).

Obtener el anchor desde AD local

$adUser = Get-ADUser -Identity "jgomez" -Properties ObjectGUID,'mS-DS-ConsistencyGuid'
$bytes = if ($adUser.'mS-DS-ConsistencyGuid') { $adUser.'mS-DS-ConsistencyGuid' } else { $adUser.ObjectGUID.ToByteArray() }
$immutableId = [Convert]::ToBase64String($bytes)
$immutableId  # Confirma que devuelve una cadena base64

Asignar el anchor en el usuario de la nube

Install-Module Microsoft.Graph -Scope CurrentUser
Connect-MgGraph -Scopes User.ReadWrite.All,Directory.AccessAsUser.All

(Opcional) Limpia un valor incorrecto previo

Update-MgUser -UserId "[usuario@dominio.com](mailto:usuario@dominio.com)" -OnPremisesImmutableId \$null

Hard match: asigna el valor correcto

Update-MgUser -UserId "[usuario@dominio.com](mailto:usuario@dominio.com)" -OnPremisesImmutableId \$immutableId

Lanza una delta sync en AADC

Start-ADSyncSyncCycle -PolicyType Delta 

Tras la sincronización, el usuario debe aparecer como Joined/Synchronized. Verifica en el portal, con Get-MgUser o desde el servidor de AADC (miisclient.exe) que el objeto está unido y recibiendo cambios del directorio local.

Diagnóstico del “último usuario” que no se fusiona

Si persiste el conflicto para un usuario concreto, sigue este listado de comprobaciones prácticas:

  • Duplicados en Exchange Online: ejecuta Get-Recipient con -IncludeSoftDeletedRecipients. Si aparece un contacto, grupo o buzón con el mismo SMTP, corrige ese objeto (retira o cambia el alias) y prueba de nuevo.
  • UPN y dominio verificado: el dominio usado en el UPN debe estar verificado en la organización y asignado al usuario en la nube. Si el UPN en la nube usa otro dominio que el local, habilita soft match por UPN o unifica primero el UPN.
  • Autoridad de atributos: evita ediciones manuales “cloud-only” en el usuario que entren en conflicto con lo que viene de AD local; tras la unión, la autoridad será AD.
  • Ámbito y reglas: si cambiaste OUs o reglas en AADC, ejecuta una Initial y revisa que el objeto esté en ámbito y sin filtros que lo excluyan.
  • Valores extraños en proxyAddresses: caracteres no permitidos, espacios, comas o entradas duplicadas con mayúsculas/minúsculas mezcladas. Limpia en AD local y vuelve a sincronizar.
  • Anchor inconsistente: si empezaste con objectGUID y luego cambiaste a mS-DS-ConsistencyGuid a mitad del proyecto, documenta y corrige ese usuario manualmente con hard match.

Tabla rápida de decisiones

SituaciónEstrategiaAcción claveComplejidadRiesgo
Usuario nunca intentado unir, UPN y SMTP ya alineadosSoft match por UPNHabilitar EnableSoftMatchOnUpn y sincronizarBajaBajo
Usuario con intentos previos fallidos por duplicadoHard matchEstablecer OnPremisesImmutableId con el anchorMediaBajo si anchor correcto
Duplicado real en otro objeto de la nubeRemediación de directorioQuitar/cambiar SMTP en el objeto incorrecto y sincronizarMediaMedio (impacto de correo)
Reglas/ámbito de AADC desactualizadosReevaluaciónActualizar ámbito y ejecutar InitialMediaBajo

Procedimiento paso a paso recomendado

  1. En AD local, alinea UPN y SMTP primario con el objeto de la nube.
  2. En Exchange Online, confirma que la dirección SMTP no existe en ningún otro objeto (incluidos eliminados).
  3. Si el usuario no ha sido intentado, prueba soft match por UPN y ejecuta una Delta.
  4. Si el usuario ya falló, realiza hard match:
    • Lee mS-DS-ConsistencyGuid o objectGUID del AD.
    • Convierte a Base64 y asígnalo a OnPremisesImmutableId del usuario en la nube.
    • Ejecuta Start-ADSyncSyncCycle -PolicyType Delta.
  5. Verifica que el usuario aparece como Joined/Synchronized y que onPremisesSyncEnabled es True.
  6. Documenta el anchor y estandariza tus scripts en Microsoft Graph.

Bloques de PowerShell de referencia

Comprobar y extraer SMTP primario en AD

Get-ADUser -Identity "jgomez" -Properties proxyAddresses |
 ForEach-Object {
   $primary = ($.proxyAddresses | Where-Object {$ -cmatch '^SMTP:'}) -replace '^SMTP:'
   [PSCustomObject]@{
     SamAccountName = $_.SamAccountName
     PrimarySMTP    = $primary
     AllProxies     = ($_.proxyAddresses -join '; ')
   }
 }

Buscar cualquier entidad que tenga un SMTP específico en Exchange Online

Connect-ExchangeOnline
$addr = "usuario@dominio.com"
Get-Recipient -ResultSize Unlimited -IncludeSoftDeletedRecipients -Filter "EmailAddresses -eq 'smtp:$addr'" |
 Sort-Object RecipientType |
 Format-Table Name, RecipientType, PrimarySmtpAddress -Auto

Obtener el anchor desde AD y forzar el hard match

# AD local
$adUser = Get-ADUser -Identity "jgomez" -Properties ObjectGUID,'mS-DS-ConsistencyGuid'
$bytes  = if ($adUser.'mS-DS-ConsistencyGuid') { $adUser.'mS-DS-ConsistencyGuid' } else { $adUser.ObjectGUID.ToByteArray() }
$immutableId = [Convert]::ToBase64String($bytes)

Nube

Install-Module Microsoft.Graph -Scope CurrentUser
Connect-MgGraph -Scopes User.ReadWrite.All,Directory.AccessAsUser.All

Limpieza previa (si aplica) y asignación

Update-MgUser -UserId "[usuario@dominio.com](mailto:usuario@dominio.com)" -OnPremisesImmutableId \$null
Update-MgUser -UserId "[usuario@dominio.com](mailto:usuario@dominio.com)" -OnPremisesImmutableId \$immutableId

Sincronización

Start-ADSyncSyncCycle -PolicyType Delta 

Verificar estado de sincronización del usuario

Get-MgUser -UserId "usuario@dominio.com" -Property onPremisesSyncEnabled, onPremisesLastSyncDateTime, onPremisesImmutableId |
 Select-Object onPremisesSyncEnabled, onPremisesLastSyncDateTime, onPremisesImmutableId

Errores frecuentes y cómo evitarlos

  • Cambiar el anchor a mitad del proyecto: evita alternar entre objectGUID y mS-DS-ConsistencyGuid. Si necesitas cambiarlo, planifica una migración de anchor controlada.
  • Editar atributos solo en la nube tras la unión: los cambios deben originarse en AD local; de lo contrario, se sobrescribirán en la próxima sincronización.
  • Ignorar la papelera de Exchange/Entra: los objetos soft-deleted también pueden retener direcciones SMTP y bloquear la unión.
  • Caracteres prohibidos o espacios: proxyAddresses es sensible a formato; elimina espacios antes o después de los dos puntos (SMTP:).
  • UPN con dominio no verificado: verifica el dominio en la organización y úsalo de forma consistente.

Buenas prácticas complementarias

  • Ejecuta IdFix antes de sincronizar lotes grandes; corrige duplicados y valores inválidos.
  • Documenta el anchor oficial de tu AADC (preferido: mS-DS-ConsistencyGuid) y consérvalo durante todo el proyecto.
  • Estandariza en Microsoft Graph para lectura/escritura de atributos en la nube; reserva MSOnline solo para características heredadas como EnableSoftMatchOnUpn.
  • Cuando ajustes el SMTP primario, preserva alias históricos como X500: si aplican, para evitar NDRs por legacyExchangeDN.
  • Tras la unión, valida SSO end‑to‑end: inicia sesión, prueba acceso a Microsoft 365 y, en Exchange híbrido, verifica Autodiscover, libre/ocupado y envío/recepción.

Checklist de verificación tras la fusión

  • El usuario en la nube muestra Sincronizado desde Active Directory y el valor onPremisesSyncEnabled = True.
  • onPremisesImmutableId tiene el Base64 del anchor correcto (mS-DS-ConsistencyGuid preferente).
  • La dirección SMTP: primaria coincide en AD y en la nube, sin duplicados en otros objetos.
  • El inicio de sesión funciona con el UPN unificado; MFA y políticas de acceso condicional aplican correctamente.
  • En miisclient.exe, el objeto aparece como Joined y sin errores de proyección ni exportación.

Preguntas y respuestas útiles

¿Perderé licencias o datos del usuario en la nube al unirlo?
No. La operación correcta es unir el objeto existente; no se crea uno nuevo. El objeto mantiene su objectId y licencias, y pasa a ser administrado por AD local.

¿Puedo revertir a “solo nube” después?
Sí, pero conlleva cambiar la autoridad del objeto, detener AADC y convertir la cuenta a “cloud-only”. No es parte de este procedimiento.

¿UPN y SMTP deben ser idénticos?
No necesariamente, pero es recomendable alinear el UPN con un dominio verificado y mantener coherencia con el SMTP primario para minimizar conflictos y fricción de usuario.

Resultado esperado

  • Con soft match por UPN habilitado y atributos alineados, los nuevos objetos/OUs se unirán automáticamente.
  • Para el usuario que ya había fallado, el hard match estableciendo OnPremisesImmutableId vía Microsoft Graph resolverá el conflicto de ProxyAddresses y realizará la fusión correcta.

Plantilla rápida de ejecución

# 1) Revisar AD local
Get-ADUser -Identity "jgomez" -Properties userPrincipalName,proxyAddresses

2) Comprobar duplicados en Exchange Online (incluye papelera)

Connect-ExchangeOnline
\$addr="[usuario@dominio.com](mailto:usuario@dominio.com)"
Get-Recipient -ResultSize Unlimited -IncludeSoftDeletedRecipients -Filter "EmailAddresses -eq 'smtp:\$addr'"

3) Si es apto para soft match (nunca intentado y alineado)

Install-Module MSOnline -Scope CurrentUser
Connect-MsolService
Set-MsolDirSyncFeature -Feature EnableSoftMatchOnUpn -Enable \$true
Start-ADSyncSyncCycle -PolicyType Delta

4) Si ya falló: hard match

\$adUser = Get-ADUser -Identity "jgomez" -Properties ObjectGUID,'mS-DS-ConsistencyGuid'
\$bytes  = if (\$adUser.'mS-DS-ConsistencyGuid') { \$adUser.'mS-DS-ConsistencyGuid' } else { \$adUser.ObjectGUID.ToByteArray() }
\$immutableId = \[Convert]::ToBase64String(\$bytes)

Install-Module Microsoft.Graph -Scope CurrentUser
Connect-MgGraph -Scopes User.ReadWrite.All,Directory.AccessAsUser.All
Update-MgUser -UserId "[usuario@dominio.com](mailto:usuario@dominio.com)" -OnPremisesImmutableId \$null
Update-MgUser -UserId "[usuario@dominio.com](mailto:usuario@dominio.com)" -OnPremisesImmutableId \$immutableId
Start-ADSyncSyncCycle -PolicyType Delta

5) Validar unión

Get-MgUser -UserId "[usuario@dominio.com](mailto:usuario@dominio.com)" -Property onPremisesSyncEnabled,onPremisesLastSyncDateTime,onPremisesImmutableId 

Con estos pasos y controles, podrás resolver el clásico bloqueo por ProxyAddresses duplicados y completar la fusión de identidades para un SSO limpio entre Exchange on‑prem y Microsoft 365.

Índice