From a7d9c0a709a594e869ebe17880c3dcd8660eabd6 Mon Sep 17 00:00:00 2001 From: Marco Francisco Date: Thu, 30 Apr 2026 22:47:26 +0100 Subject: [PATCH 1/3] Update AuthServerCheck, EWSVirtualDirectoryCheckOAuth, CheckIfExchangeServer, CheckParameters, hostOutputIntraOrgConEnabled, and HTML configuration rendering to align on-prem hybrid free/busy OAuth validation with modern EvoSTS-based auth and fix related output issues --- .../Functions/CommonFunctions.ps1 | 14 ++++++++------ .../Functions/OnPremOAuthFunctions.ps1 | 18 ++++++++++-------- .../FreeBusyChecker/Functions/hostOutput.ps1 | 2 +- .../FreeBusyChecker/Functions/htmlContent.ps1 | 2 +- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/Diagnostics/FreeBusyChecker/Functions/CommonFunctions.ps1 b/Diagnostics/FreeBusyChecker/Functions/CommonFunctions.ps1 index bfdb104bc5..436c93663f 100644 --- a/Diagnostics/FreeBusyChecker/Functions/CommonFunctions.ps1 +++ b/Diagnostics/FreeBusyChecker/Functions/CommonFunctions.ps1 @@ -4,7 +4,7 @@ function Test-ExchangeOnlineConnection { Write-Host -ForegroundColor Green " Checking Exchange Online Configuration" Write-Host " Testing Connection to Exchange Online with EO Prefix." try { - $CheckExoMailbox = Get-EOMailbox $Script:UserOnline -ErrorAction Stop + $CheckExoMailbox = get-EOMailbox $Script:UserOnline -ErrorAction Stop if ($null -ne $CheckExoMailbox) { return $true } else { @@ -24,12 +24,14 @@ function FetchEWSInformation { if (-not $Script:WebServicesVirtualDirectory -or -not $Script:WebServicesVirtualDirectoryOAuth) { $Script:WebServicesVirtualDirectory = Get-WebServicesVirtualDirectory -Server $Script:Server | Select-Object Identity, Name, ExchangeVersion, *Authentication*, *url -ErrorAction SilentlyContinue $Script:WebServicesVirtualDirectoryOAuth = $Script:WebServicesVirtualDirectory - $Script:ExchangeOnPremEWS = ($Script:WebServicesVirtualDirectory.externalURL.AbsoluteUri) } } function CheckIfExchangeServer { - $exchangeShell = Confirm-ExchangeShell - if (-not($exchangeShell.ShellLoaded)) { + param ( + [string]$Server + ) + $exchangeServer = Get-ExchangeServer $Server -ErrorAction SilentlyContinue + if (!$exchangeServer) { Write-Host "$Server is not an Exchange Server. This script should be run in Exchange Server Management Shell" exit } @@ -42,10 +44,10 @@ function CheckParameters { if ([string]::IsNullOrWhiteSpace($Script:ExchangeOnPremLocalDomain)) { $MissingParameters += "Exchange On Premises Local Domain. Example: . 'C:\scripts\FreeBusyChecker\FreeBusyChecker.ps1' -OnPremisesUser John@Contoso.com" } - if ([string]::IsNullOrWhiteSpace($exchangeOnPremDomain)) { + if ([string]::IsNullOrWhiteSpace($Script:ExchangeOnPremDomain)) { $MissingParameters += "Exchange On Premises Domain. Example: -OnPremLocalDomain Contoso.local" } - if ([string]::IsNullOrWhiteSpace($exchangeOnPremEWS)) { + if ([string]::IsNullOrWhiteSpace($Script:ExchangeOnPremEWS)) { $MissingParameters += "Exchange On Premises EWS Virtual Directory External URL. Example: 'C:\FreeBusyChecker.ps1' -OnPremEWSUrl https://mail.contoso.com/EWS/Exchange.asmx" } if ([string]::IsNullOrWhiteSpace($Script:UserOnPrem)) { diff --git a/Diagnostics/FreeBusyChecker/Functions/OnPremOAuthFunctions.ps1 b/Diagnostics/FreeBusyChecker/Functions/OnPremOAuthFunctions.ps1 index 27c0deb39f..ab925b49e8 100644 --- a/Diagnostics/FreeBusyChecker/Functions/OnPremOAuthFunctions.ps1 +++ b/Diagnostics/FreeBusyChecker/Functions/OnPremOAuthFunctions.ps1 @@ -49,9 +49,9 @@ function IntraOrgConCheck { } function AuthServerCheck { #PrintDynamicWidthLine - Write-Host -ForegroundColor Green " Get-AuthServer | Select Name,IssuerIdentifier,TokenIssuingEndpoint,AuthMetadataUrl,Enabled" + Write-Host -ForegroundColor Green " Get-AuthServer | Select Name, Realm, IssuerIdentifier, TokenIssuingEndpoint, AuthMetadataUrl, Enabled" PrintDynamicWidthLine - $AuthServer = Get-AuthServer | Where-Object { $_.Name -like "ACS*" } | Select-Object Name, IssuerIdentifier, TokenIssuingEndpoint, AuthMetadataUrl, Enabled + $AuthServer = Get-AuthServer | Where-Object { $_.Name -like "EvoSts*" } | Select-Object Name, Realm, IssuerIdentifier, TokenIssuingEndpoint, AuthMetadataUrl, Enabled $AuthServer $Script:tDAuthServerIssuerIdentifier = $AuthServer.IssuerIdentifier $Script:tDAuthServerTokenIssuingEndpoint = $AuthServer.TokenIssuingEndpoint @@ -61,30 +61,30 @@ function AuthServerCheck { Write-Host -ForegroundColor Green " Summary - Auth Server" PrintDynamicWidthLine Write-Host -ForegroundColor White " IssuerIdentifier: " - if ($AuthServer.IssuerIdentifier -like "00000001-0000-0000-c000-000000000000" ) { + if ($AuthServer.IssuerIdentifier -like "https://sts.windows.net/$($AuthServer.Realm)/" ) { Write-Host -ForegroundColor Green " " $AuthServer.IssuerIdentifier $Script:tDAuthServerIssuerIdentifierColor = "green" } else { Write-Host -ForegroundColor Red " IssuerIdentifier appears not to be correct." - Write-Host -ForegroundColor White " Should be 00000001-0000-0000-c000-000000000000" + Write-Host -ForegroundColor White " Should be https://sts.windows.net//" $Script:tDAuthServerIssuerIdentifierColor = "red" } Write-Host -ForegroundColor White " TokenIssuingEndpoint: " - if ($AuthServer.TokenIssuingEndpoint -like "https://accounts.accesscontrol.windows.net/*" -and $AuthServer.TokenIssuingEndpoint -like "*/tokens/OAuth/2" ) { + if ($AuthServer.TokenIssuingEndpoint -like "https://login.windows.net/common/oauth2/token*" ) { Write-Host -ForegroundColor Green " " $AuthServer.TokenIssuingEndpoint $Script:tDAuthServerTokenIssuingEndpointColor = "green" } else { Write-Host -ForegroundColor Red " TokenIssuingEndpoint appears not to be correct." - Write-Host -ForegroundColor White " Should be https://accounts.accesscontrol.windows.net//tokens/OAuth/2" + Write-Host -ForegroundColor White " Should be https://login.windows.net/common/oauth2/token" $Script:tDAuthServerTokenIssuingEndpointColor = "red" } Write-Host -ForegroundColor White " AuthMetadataUrl: " - if ($AuthServer.AuthMetadataUrl -like "https://accounts.accesscontrol.windows.net/*" -and $AuthServer.TokenIssuingEndpoint -like "*/tokens/OAuth/2" ) { + if ($AuthServer.AuthMetadataUrl -like "https://login.windows.net/*/federationmetadata/2007-06/federationmetadata.xml" ) { Write-Host -ForegroundColor Green " " $AuthServer.AuthMetadataUrl $Script:tDAuthServerAuthMetadataUrlColor = "green" } else { Write-Host -ForegroundColor Red " AuthMetadataUrl appears not to be correct." - Write-Host -ForegroundColor White " Should be https://accounts.accesscontrol.windows.net//Metadata/json/1" + Write-Host -ForegroundColor White " Should be https://login.windows.net//FederationMetadata/2007-06/FederationMetadata.xml" $Script:tDAuthServerAuthMetadataUrlColor = "red" } Write-Host -ForegroundColor White " Enabled: " @@ -541,6 +541,7 @@ function AutoDVirtualDCheckOauth { function EWSVirtualDirectoryCheckOAuth { Write-Host -ForegroundColor Green " Get-WebServicesVirtualDirectory -Server $($server)| Select Identity,Name,ExchangeVersion,*Authentication*,*url" PrintDynamicWidthLine + FetchEWSInformation $W = $WebServicesVirtualDirectoryOAuth | Format-List $W EWSVirtualDirectoryCheckOAuthHtmlHead @@ -623,6 +624,7 @@ function EWSVirtualDirectoryCheckOAuth { } Write-Host -ForegroundColor White " Should be True" } + #PrintDynamicWidthLine Write-Host -ForegroundColor White "`n WindowsAuthentication:" if ($WebServicesVirtualDirectoryOauth.WindowsAuthentication -eq "True") { foreach ( $ser in $WebServicesVirtualDirectoryOauth) { diff --git a/Diagnostics/FreeBusyChecker/Functions/hostOutput.ps1 b/Diagnostics/FreeBusyChecker/Functions/hostOutput.ps1 index 0404b5af92..afe45451e7 100644 --- a/Diagnostics/FreeBusyChecker/Functions/hostOutput.ps1 +++ b/Diagnostics/FreeBusyChecker/Functions/hostOutput.ps1 @@ -83,7 +83,7 @@ function hostOutputIntraOrgConEnabled($Auth) { Write-Host -ForegroundColor White " -> Running for OAuth only as OAuth takes precedence over DAuth;" Write-Host -ForegroundColor White "`n This script can be Run using the -Auth All parameter to Check for both OAuth and DAuth configuration. `n `n Example: ./FreeBusyChecker.ps1 -Auth All" Write-Host -ForegroundColor White "`n This script can be Run using the -Auth DAuth parameter to Check for DAuth configuration only. `n `n Example: ./FreeBusyChecker.ps1 -Auth DAuth" - lookupMethodDAuthHtml + lookupMethodOAuthHtml } if ($Auth -like "All") { lookupMethodCheckAllHtml diff --git a/Diagnostics/FreeBusyChecker/Functions/htmlContent.ps1 b/Diagnostics/FreeBusyChecker/Functions/htmlContent.ps1 index bd4e69343e..b4c445a6ab 100644 --- a/Diagnostics/FreeBusyChecker/Functions/htmlContent.ps1 +++ b/Diagnostics/FreeBusyChecker/Functions/htmlContent.ps1 @@ -119,7 +119,7 @@ margin-right: 1%; -
+

Configuration:

TLS 1.2 should be Enabled in order for Hybrid Free Busy to work. To confirm TLS Settings please Run the HealthChecker Script

  • Microsoft Exchange Health Checker Script
  • From 666e9f233c15c7ab4942cd40d6133084ad4aa07b Mon Sep 17 00:00:00 2001 From: Marco Francisco <98214653+MarcoLFrancisco@users.noreply.github.com> Date: Thu, 30 Apr 2026 23:27:13 +0100 Subject: [PATCH 2/3] Update Diagnostics/FreeBusyChecker/Functions/CommonFunctions.ps1 Suggestion accepted Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../FreeBusyChecker/Functions/CommonFunctions.ps1 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Diagnostics/FreeBusyChecker/Functions/CommonFunctions.ps1 b/Diagnostics/FreeBusyChecker/Functions/CommonFunctions.ps1 index 436c93663f..7b272aa500 100644 --- a/Diagnostics/FreeBusyChecker/Functions/CommonFunctions.ps1 +++ b/Diagnostics/FreeBusyChecker/Functions/CommonFunctions.ps1 @@ -24,6 +24,16 @@ function FetchEWSInformation { if (-not $Script:WebServicesVirtualDirectory -or -not $Script:WebServicesVirtualDirectoryOAuth) { $Script:WebServicesVirtualDirectory = Get-WebServicesVirtualDirectory -Server $Script:Server | Select-Object Identity, Name, ExchangeVersion, *Authentication*, *url -ErrorAction SilentlyContinue $Script:WebServicesVirtualDirectoryOAuth = $Script:WebServicesVirtualDirectory + + if ([string]::IsNullOrWhiteSpace($Script:ExchangeOnPremEWS)) { + $externalUrl = $Script:WebServicesVirtualDirectory | + Where-Object { $null -ne $_.ExternalUrl } | + Select-Object -First 1 -ExpandProperty ExternalUrl + + if ($null -ne $externalUrl) { + $Script:ExchangeOnPremEWS = $externalUrl.ToString() + } + } } } function CheckIfExchangeServer { From 619cc332e1c336635868017a6e4ebbd7ca15ddb9 Mon Sep 17 00:00:00 2001 From: Marco Francisco <98214653+MarcoLFrancisco@users.noreply.github.com> Date: Fri, 8 May 2026 11:23:19 +0100 Subject: [PATCH 3/3] Apply suggestion from @Copilot Suggestion accepted Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../FreeBusyChecker/Functions/OnPremOAuthFunctions.ps1 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Diagnostics/FreeBusyChecker/Functions/OnPremOAuthFunctions.ps1 b/Diagnostics/FreeBusyChecker/Functions/OnPremOAuthFunctions.ps1 index ab925b49e8..ff308def1f 100644 --- a/Diagnostics/FreeBusyChecker/Functions/OnPremOAuthFunctions.ps1 +++ b/Diagnostics/FreeBusyChecker/Functions/OnPremOAuthFunctions.ps1 @@ -51,7 +51,10 @@ function AuthServerCheck { #PrintDynamicWidthLine Write-Host -ForegroundColor Green " Get-AuthServer | Select Name, Realm, IssuerIdentifier, TokenIssuingEndpoint, AuthMetadataUrl, Enabled" PrintDynamicWidthLine - $AuthServer = Get-AuthServer | Where-Object { $_.Name -like "EvoSts*" } | Select-Object Name, Realm, IssuerIdentifier, TokenIssuingEndpoint, AuthMetadataUrl, Enabled + $AuthServer = Get-AuthServer | + Where-Object { $_.Name -like "EvoSts*" } | + Sort-Object Name | + Select-Object -First 1 Name, Realm, IssuerIdentifier, TokenIssuingEndpoint, AuthMetadataUrl, Enabled $AuthServer $Script:tDAuthServerIssuerIdentifier = $AuthServer.IssuerIdentifier $Script:tDAuthServerTokenIssuingEndpoint = $AuthServer.TokenIssuingEndpoint