Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion powershell/public/Connect-Maester.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@
$ExoUPN = Get-MtExo -Request ConnectionInformation | Select-Object -ExpandProperty UserPrincipalName -First 1 -ErrorAction SilentlyContinue
if ($ExoUPN) {
Write-Host "`nAttempting to connect to the Security & Compliance PowerShell using UPN '$ExoUPN' derived from the ExchangeOnline connection." -ForegroundColor Yellow
Connect-IPPSSession -BypassMailboxAnchoring -UserPrincipalName $ExoUPN -ShowBanner:$false
Connect-IPPSSession -BypassMailboxAnchoring -UserPrincipalName $ExoUPN -ConnectionUri $Environments[$ExchangeEnvironmentName].ConnectionUri -AzureADAuthorizationEndpointUri $Environments[$ExchangeEnvironmentName].AuthZEndpointUri -ShowBanner:$false
} else {
Write-Host "`nFailed to connect to the Security & Compliance PowerShell. Please ensure you are connected to Exchange Online first." -ForegroundColor Red
}
Expand Down Expand Up @@ -258,6 +258,20 @@

Write-Verbose "🦒 Connecting to Microsoft Graph with parameters:"
Write-Verbose ($connectParams | ConvertTo-Json -Depth 5)

# On Windows, the Microsoft Graph SDK uses Windows Account Manager (WAM) as the authentication broker by default.
# WAM may not support national cloud accounts (e.g. GCC High, DoD, China) in the account picker.
# Warn users to use -UseDeviceCode if they encounter authentication issues.
if ($Environment -ne 'Global' -and ($IsWindows -or $PSVersionTable.PSEdition -eq 'Desktop') -and -not $UseDeviceCode) {
# Build a suggested retry command using only the non-default parameter values provided by the caller.
$retryCmd = "Connect-Maester -UseDeviceCode -Environment $Environment"
if ($AzureEnvironment -ne 'AzureCloud') { $retryCmd += " -AzureEnvironment $AzureEnvironment" }
if ($ExchangeEnvironmentName -ne 'O365Default') { $retryCmd += " -ExchangeEnvironmentName $ExchangeEnvironmentName" }
Comment on lines +266 to +269
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The suggested $retryCmd doesn’t currently include several caller-supplied non-default parameters (e.g., -TenantId, -GraphClientId, -Service, -SendMail, -SendTeamsMessage, -Privileged, -TeamsEnvironmentName). This can cause the copy/paste “retry” command to change behavior vs the original invocation. Consider generating the retry command from $PSBoundParameters (adding UseDeviceCode=$true, preserving any explicitly provided params, and optionally omitting values that match defaults) so the guidance is accurate and future-proof.

Suggested change
# Build a suggested retry command using only the non-default parameter values provided by the caller.
$retryCmd = "Connect-Maester -UseDeviceCode -Environment $Environment"
if ($AzureEnvironment -ne 'AzureCloud') { $retryCmd += " -AzureEnvironment $AzureEnvironment" }
if ($ExchangeEnvironmentName -ne 'O365Default') { $retryCmd += " -ExchangeEnvironmentName $ExchangeEnvironmentName" }
# Build a suggested retry command based on the caller-supplied parameters, forcing UseDeviceCode = $true.
$retryParams = @{}
foreach ($entry in $PSBoundParameters.GetEnumerator()) {
$retryParams[$entry.Key] = $entry.Value
}
$retryParams['UseDeviceCode'] = $true
$retryCmd = 'Connect-Maester'
foreach ($entry in $retryParams.GetEnumerator()) {
$name = $entry.Key
$value = $entry.Value
if ($null -eq $value) {
continue
}
# Handle switch/bool parameters: include only when $true.
if ($value -is [bool]) {
if ($value) {
$retryCmd += " -$name"
}
continue
}
# Handle collections by joining values into a single, quoted string.
if ($value -is [System.Collections.IEnumerable] -and -not ($value -is [string])) {
$joined = ($value | ForEach-Object { $_.ToString() }) -join ','
$escaped = $joined -replace "'", "''"
$retryCmd += " -$name '$escaped'"
continue
}
# Default: quote string values and escape single quotes.
$stringValue = [string]$value
$escapedValue = $stringValue -replace "'", "''"
$retryCmd += " -$name '$escapedValue'"
}

Copilot uses AI. Check for mistakes.
Write-Host "`n💡 Tip: When connecting to the '$Environment' environment on Windows, Windows Account Manager (WAM) may not recognize national cloud accounts in the sign-in prompt." -ForegroundColor Yellow
Write-Host " If authentication fails or is cancelled, add the -UseDeviceCode parameter to authenticate via browser instead of WAM:`n" -ForegroundColor Yellow
Write-Host " $retryCmd`n" -ForegroundColor Cyan
}

Connect-MgGraph @connectParams

#ensure TenantId
Expand All @@ -268,6 +282,19 @@
} catch [Management.Automation.CommandNotFoundException] {
Write-Host "`nThe Graph PowerShell module is not installed. Please install the module using the following command. For more information see https://learn.microsoft.com/powershell/microsoftgraph/installation" -ForegroundColor Red
Write-Host "`Install-Module Microsoft.Graph.Authentication -Scope CurrentUser`n" -ForegroundColor Yellow
} catch {
# For non-global environments on Windows, WAM (Windows Account Manager) may not support national cloud accounts,
# causing authentication to fail or be cancelled. Provide actionable guidance to the user.
if ($Environment -ne 'Global' -and ($IsWindows -or $PSVersionTable.PSEdition -eq 'Desktop') -and -not $UseDeviceCode) {
$retryCmd = "Connect-Maester -UseDeviceCode -Environment $Environment"
if ($AzureEnvironment -ne 'AzureCloud') { $retryCmd += " -AzureEnvironment $AzureEnvironment" }
if ($ExchangeEnvironmentName -ne 'O365Default') { $retryCmd += " -ExchangeEnvironmentName $ExchangeEnvironmentName" }
Write-Host "`n💡 Authentication failed for the '$Environment' environment on Windows." -ForegroundColor Yellow
Write-Host " Windows Account Manager (WAM) may not support national cloud accounts in the sign-in prompt." -ForegroundColor Yellow
Write-Host " Run Connect-Maester with -UseDeviceCode to authenticate via browser instead of WAM:`n" -ForegroundColor Yellow
Write-Host " $retryCmd`n" -ForegroundColor Cyan
}
Comment on lines +285 to +296
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The generic catch {} will run for any failure in Connect-MgGraph, but the message printed is always “Authentication failed… WAM may not support…”. For non-authentication failures (invalid tenant, network/DNS issues, module bugs), this guidance is misleading. Consider narrowing this guidance to known auth-cancellation / broker-related exceptions (or checking the error record/exception message) so the message is only shown when it’s likely relevant.

Copilot uses AI. Check for mistakes.
throw
}
}
}
Expand Down
Loading