Exchange Hybrid Free/Busy Not Working: Complete Troubleshooting Guide (OAuth, Dedicated Hybrid App & Federation Trust)

When cloud users see hatched (no information) blocks for on-premises colleagues in the Outlook Scheduling Assistant — or the other way round — cross-premises free/busy is broken. When I first wrote this post in 2014, the fix was almost always a Federation Trust metadata refresh. In 2026 there are more moving parts:

  • Modern hybrid uses OAuth through an IntraOrganizationConnector. The older DAuth method (Federation Trust + Organization Relationship) is only a fallback.
  • Since 31 October 2025, Exchange Online blocks hybrid EWS calls that use the shared Office 365 Exchange Online service principal. Every hybrid org must use the dedicated Exchange hybrid application.
  • An expired or rotated Exchange Auth certificate silently breaks OAuth.

This guide walks through all of them in the order they most often fail.


How a Cross-Premises Free/Busy Lookup Works

Hybrid Free/Busy Decision Path (OAuth First, DAuth Fallback)
1. Request
User Opens Scheduling Assistant
  • Target mailbox is on the other side (MailUser / RemoteMailbox)
  • Lookup uses the target's TargetAddress domain
2. OAuth (Preferred)
IntraOrganizationConnector
  • Token issued for the dedicated hybrid app
  • Signed with the Exchange Auth certificate
3. DAuth (Fallback)
Organization Relationship
  • Used only if no enabled IOC matches
  • Depends on Federation Trust metadata
4. Target EWS
Availability Service Answers
  • On-prem: https://mail.contoso.com/EWS/Exchange.asmx
  • Cloud: https://outlook.office365.com/EWS/Exchange.asmx

Step 1: Find Out Which Direction Is Broken

Test both directions with real users. Note which ones fail:

ViewerTargetFails?Most likely cause
Cloud userOn-prem mailbox☐Dedicated hybrid app, on-prem EWS publishing, Auth certificate
On-prem userCloud mailbox☐On-prem IOC / AuthServer, outbound proxy, TargetAddress
BothBoth☐Expired Auth certificate, OAuth disabled, wrong build
Then check how the target recipient is stamped. A wrong TargetAddress (ExternalEmailAddress for remote mailboxes) sends the lookup to the wrong forest:
POWERSHELL
# On-premises Exchange Management Shell
Get-RemoteMailbox [email protected] | Select-Object PrimarySmtpAddress, RemoteRoutingAddress

# Exchange Online PowerShell
Get-MailUser [email protected] | Select-Object PrimarySmtpAddress, ExternalEmailAddress

RemoteRoutingAddress should be [email protected]. ExternalEmailAddress should point to an on-premises SMTP domain that matches the IOC/Organization Relationship.


Step 2: Confirm the Dedicated Exchange Hybrid App Is in Place

This is the number one cause of hybrid free/busy failures since late 2025. If the on-premises org still uses the shared first-party service principal, cloud-to-on-prem free/busy, MailTips and profile pictures stop working.

Prerequisites: Exchange Server SE (any build), Exchange 2019 CU14/CU15 or Exchange 2016 CU23 with the April 2025 HU or later.

POWERSHELL
# On-premises: is the dedicated app configured? (ApplicationIdentifier should NOT be the
# well-known Exchange Online app ID 00000002-0000-0ff1-ce00-000000000000)
Get-AuthServer | Where-Object { $_.Type -eq 'AzureAD' } |
    Select-Object Name, Enabled, ApplicationIdentifier, DomainName

Get-SettingOverride | Where-Object { $_.ComponentName -eq 'Global' -and $_.SectionName -eq 'ExchangeOnpremAsThirdPartyAppId' } |
    Select-Object Name, Parameters

If the override is missing, run Microsoft's script from an Exchange server (Organization Management on-prem + Application Administrator or Global Administrator in Entra):

POWERSHELL
.\ConfigureExchangeHybridApplication.ps1 -FullyConfigureExchangeHybridApplication

# After confirming free/busy works, remove the old keys from the shared service principal
.\ConfigureExchangeHybridApplication.ps1 -ResetFirstPartyServicePrincipalKeyCredentials

The latest Hybrid Configuration Wizard can also create the dedicated app for you. Keep your Exchange servers on the latest Security Update (SU), because Microsoft regularly ships hybrid availability fixes in SUs. Check the SU release notes for "free/busy" before you troubleshoot further.


Step 3: Test OAuth in Both Directions

Test-OAuthConnectivity is the single most useful cmdlet here. Run it from both sides:

POWERSHELL
# On-premises -> Exchange Online
Test-OAuthConnectivity -Service EWS `
    -TargetUri https://outlook.office365.com/ews/exchange.asmx `
    -Mailbox [email protected] -Verbose | Format-List ResultType, Detail

# Exchange Online -> on-premises (run in Exchange Online PowerShell)
Test-OAuthConnectivity -Service EWS `
    -TargetUri https://mail.contoso.com/metadata/json/1 `
    -Mailbox [email protected] -Verbose | Format-List ResultType, Detail

ResultType : Success means the token flow works. In the Detail output, look for:

  • The certificate referenced by token with key ... could not be located — the Auth certificate on-prem doesn't match what Entra has. Go to Step 4.
  • (401) Unauthorized from on-prem EWS — on-prem EWS/Autodiscover isn't published, a reverse proxy is doing pre-authentication, or the dedicated app isn't set up.
  • The remote name could not be resolved / proxy errors — on-prem servers can't reach login.microsoftonline.com or outlook.office365.com. Check Get-ExchangeServer | Select Name, InternetWebProxy.

Step 4: Check the Exchange Auth Certificate

OAuth tokens are signed with the certificate in Get-AuthConfig. If it expired or was renewed without re-running HCW, OAuth breaks in both directions.

POWERSHELL
$auth = Get-AuthConfig
Get-ExchangeCertificate -Thumbprint $auth.CurrentCertificateThumbprint |
    Select-Object Thumbprint, Subject, NotAfter, @{n='DaysLeft';e={($_.NotAfter  (Get-Date)).Days}}

$auth | Select-Object CurrentCertificateThumbprint, NextCertificateThumbprint, NextCertificateEffectiveDate

If DaysLeft is negative or close to zero, follow Microsoft's Renew the Auth certificate procedure (New-ExchangeCertificate → Set-AuthConfig -NewCertificateThumbprint ... -NewCertificateEffectiveDate → Set-AuthConfig -PublishCertificate). Then re-run ConfigureExchangeHybridApplication.ps1 or HCW so the new public key is uploaded to Entra ID.


Step 5: Verify the IntraOrganizationConnector on Both Sides

POWERSHELL
# On-premises
Get-IntraOrganizationConnector | Select-Object Name, Enabled, TargetAddressDomains, DiscoveryEndpoint

# Exchange Online
Get-IntraOrganizationConnector | Select-Object Name, Enabled, TargetAddressDomains, DiscoveryEndpoint
Get-OrganizationConfig | Select-Object OAuth2ClientProfileEnabled

What correct looks like:

  • On-prem IOC: TargetAddressDomains = contoso.mail.onmicrosoft.com, DiscoveryEndpoint = https://autodiscover-s.outlook.com/autodiscover/autodiscover.svc, Enabled = True.
  • Cloud IOC: TargetAddressDomains = your on-prem SMTP domain(s), DiscoveryEndpoint = https://mail.contoso.com/autodiscover/autodiscover.svc, Enabled = True.
Gotcha: Only one enabled IOC may cover a given domain. If an old IOC or a stale test connector also lists the domain, the lookup can hit the wrong endpoint.

Step 6: DAuth Fallback — The Original 2014 Fix (Federation Trust Refresh)

If you have no IOC (classic hybrid) or OAuth is intentionally disabled, free/busy goes through the Organization Relationship and Federation Trust. The classic failure from the original post still happens:

POWERSHELL
Test-FederationTrust -UserIdentity [email protected]
POWERSHELL
Id      : FederationMetadata
Type    : Error
Message : The federation trust doesn't contain the same certificates published by the security token service in its federation metadata.

Id      : TokenValidation
Type    : Error
Message : Failed to validate delegation token.

Microsoft rotates the federation gateway's signing certificates. When on-prem Exchange misses the update (often because the server can't reach the metadata URL through a proxy), delegation tokens fail validation. Refresh the metadata:

POWERSHELL
Get-FederationTrust | Set-FederationTrust -RefreshMetadata
Test-FederationTrust -UserIdentity [email protected]   # all checks should now report Success

Then confirm the Organization Relationship on both sides allows free/busy:

POWERSHELL
Get-OrganizationRelationship | Select-Object Name, DomainNames, Enabled, FreeBusyAccessEnabled, FreeBusyAccessLevel, TargetApplicationUri, TargetAutodiscoverEpr

Test-OrganizationRelationship -Identity "On-premises to O365*" -UserIdentity [email protected] -Verbose

FreeBusyAccessLevel should be LimitedDetails (or AvailabilityOnly). TargetApplicationUri on-prem should be outlook.com.

Tip: When I ran these checks against the LAB 365 tenant, I found a leftover Organization Relationship from an old cross-tenant test, with FreeBusyAccessEnabled : False and no TargetAutodiscoverEpr. Stale relationships like this are harmless until their domain list overlaps a real partner or your own hybrid domain. Review Get-OrganizationRelationship during every hybrid health check.

Step 7: One-Shot On-Premises Health Report

Run this in the Exchange Management Shell to collect everything above in one pass:

POWERSHELL
function Test-HybridFreeBusyHealth {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)] [string]$OnPremMailbox,
        [string]$EwsUri = 'https://outlook.office365.com/ews/exchange.asmx'
    )

    $auth     = Get-AuthConfig
    $authCert = Get-ExchangeCertificate -Thumbprint $auth.CurrentCertificateThumbprint -ErrorAction SilentlyContinue
    $override = Get-SettingOverride | Where-Object SectionName -eq 'ExchangeOnpremAsThirdPartyAppId'
    $ioc      = Get-IntraOrganizationConnector | Where-Object Enabled
    $oauth    = Test-OAuthConnectivity -Service EWS -TargetUri $EwsUri -Mailbox $OnPremMailbox -ErrorAction SilentlyContinue
    $fed      = Test-FederationTrust -UserIdentity $OnPremMailbox -ErrorAction SilentlyContinue

    [PSCustomObject]@{
        ExchangeBuilds         = ((Get-ExchangeServer | Select-Object -ExpandProperty AdminDisplayVersion | Sort-Object -Unique) -join '; ')
        DedicatedHybridApp     = [bool]$override
        AuthCertDaysLeft       = if ($authCert) { ($authCert.NotAfter  (Get-Date)).Days } else { 'NOT FOUND' }
        EnabledIOCs            = ($ioc.Name -join '; ')
        IOCTargetDomains       = ($ioc.TargetAddressDomains -join '; ')
        OAuthToEXO             = if ($oauth) { $oauth.ResultType } else { 'Test failed to run' }
        FederationTrustErrors  = (($fed | Where-Object Type -eq 'Error').Id -join '; ')
    }
}

# Example
Test-HybridFreeBusyHealth -OnPremMailbox [email protected]

If everything looks fine but free/busy still fails, use Microsoft's Remote Connectivity Analyzer → Free/Busy test (testconnectivity.microsoft.com). It runs the cloud-to-on-prem lookup from outside your network and shows the exact HTTP failure.