Microsoft 365 PowerShell authentication failures: three bugs, one fix.

I was building a Microsoft 365 tenant security audit script that needed both Microsoft Graph PowerShell SDK and Exchange Online Management running in the same session. Simple enough on paper. In practice I hit three separate authentication failures before finding a method that works reliably across every combination I tested.

the background

Tony Redmond at office365itpros.com has documented the MSAL assembly clash between these modules extensively. What I found during testing goes further than connection order. There are three distinct failure modes, each with a different root cause, and one authentication method that eliminates all of them.

Here is the complete evidence from real tests run on a live tenant.

the test environment

All tests were run on Windows 11 with:

  • Exchange Online Management module v3.9.2
  • Microsoft Graph PowerShell SDK v2.35.1
  • PowerShell 7.6.1 (pwsh)
  • Windows PowerShell 5.1 (powershell)

Two connection orders were tested for each scenario:

  • Microsoft Graph connects first, then Exchange Online
  • Exchange Online connects first, then Microsoft Graph

Two authentication methods were tested:

  • Device code authentication (-UseDeviceCode and -Device)
  • Certificate based app-only authentication

the complete test matrix

Test Shell Connection Order Auth Method EXO Login Graph Login EXO Cmdlets Graph Cmdlets Result
1 PS 7.6.1 Graph first Device code Success Success Unknown FAIL FAIL
2 PS 7.6.1 EXO first Device code Success Success Unknown FAIL FAIL
3 PS 5.1 Graph first Device code FAIL Success N/A N/A FAIL
4 PS 5.1 EXO first Device code Success FAIL N/A N/A FAIL
5 PS 5.1 Graph first Cert auth Success Success Success Success PASS
6 PS 5.1 EXO first Cert auth Success FAIL N/A N/A FAIL
7 PS 7.6.1 Graph first Cert auth Success Success Success Success PASS
8 PS 7.6.1 EXO first Cert auth Success Success Success Success PASS

Three combinations pass end to end. All three use certificate based app-only authentication. Two work on PowerShell 7 regardless of connection order. One works on PowerShell 5.1, but only when Microsoft Graph connects before Exchange Online.

Test 5 was verified end to end by running both the full 20-check tenant audit script and the mailbox report script on Windows PowerShell 5.1 with certificate authentication. Both scripts completed successfully with no errors. All 20 audit checks ran and the mailbox report generated correctly.

bug one: the MSAL assembly clash

This is the failure Tony Redmond documented. In plain English, think of MSAL as a shared key cutting machine that both modules need to make keys to get into Microsoft 365. On PowerShell 5.1, the first module to run installs its own version of that machine. When the second module arrives and tries to use it, the machine is a slightly different model and the second module cannot operate it.

On PowerShell 5.1 with Graph connecting first, Exchange Online fails with this error:

// error
Method not found: 'Microsoft.Identity.Client.PublicClientApplicationBuilder
Microsoft.Identity.Client.Broker.BrokerExtension.WithBroker(
    Microsoft.Identity.Client.PublicClientApplicationBuilder,
    Microsoft.Identity.Client.BrokerOptions)'.

Graph SDK loaded its MSAL version first. Exchange Online V3 looked for a specific method called WithBroker in that version and could not find it.

Tony documented this in detail. His September 2025 post covers the full history of the clash across module versions, and his January 2026 update references the same issue.

bug two: Graph SDK module load failure

Reversing the order on PowerShell 5.1 creates a completely different problem. Exchange Online connects successfully. Then Graph SDK fails before even authenticating:

// error
The 'Connect-MgGraph' command was found in the module
'Microsoft.Graph.Authentication', but the module could not be loaded.

In plain English, Exchange Online loaded its version of the shared key machine. When Graph SDK arrived it could not even unpack its own tools because the machine already installed was incompatible with what Graph SDK needed to get started.

This is not an authentication error. The Graph SDK module cannot initialize at all. Tony's documented fix of connecting Exchange Online before Graph helps with Bug One but creates Bug Two instead. On PowerShell 5.1 with device code auth, both connection orders fail. Just with different errors.

bug three: DeviceCodeCredential token cache failure

This one is the most confusing because everything appears to work at first. On PowerShell 7 with the latest Graph SDK, both modules connect successfully regardless of order. The device code flow completes, you authenticate in the browser, no assembly errors. Then the first Graph cmdlet you run fails:

// error
DeviceCodeCredential authentication failed: Object reference
not set to an instance of an object.

In plain English, you successfully showed your ID at the front door and received a visitor badge. But when you tried to use the badge to open the first door inside the building, the badge reader said the badge was invalid. The badge was issued correctly, but something went wrong when it was stored in your pocket.

Confirmed Microsoft SDK bug. Tracked as GitHub issue microsoftgraph/msgraph-sdk-powershell#3495, opened January 2026, with a regression re-reported in April 2026.

Root cause confirmed by SDK maintainer ramsessanchez: Microsoft.Graph v2.34 bumped Azure.Identity to enable WAM as the default authentication broker. The new Azure.Identity changed how tokens are cached. The DeviceCodeCredential code path no longer handles the cache correctly. The token is acquired successfully at login but becomes unusable the moment a cmdlet tries to use it.

This reproduces on v2.34, v2.35, and v2.35.1 on both PowerShell 7 and PowerShell 5.1. Connection order does not fix this. It is a token cache bug, not an assembly conflict.

the fix: certificate based app-only authentication

Tests 7 and 8 pass completely end to end. Test 5 also passes on PowerShell 5.1 when Graph connects first. All three use certificate based app-only authentication:

// powershell
# Connect Microsoft Graph with certificate auth
Connect-MgGraph `
    -ClientId "your-app-id" `
    -TenantId "your-tenant-id" `
    -CertificateThumbprint "your-cert-thumbprint"

# Connect Exchange Online with certificate auth
Connect-ExchangeOnline `
    -AppId "your-app-id" `
    -Organization "yourtenant.onmicrosoft.com" `
    -CertificateThumbprint "your-cert-thumbprint"

Why cert auth fixes all three bugs:

Bug One and Two. Certificate auth does not use the MSAL interactive broker at all. It authenticates directly using the certificate without needing the shared key cutting machine. No broker. No WithBroker method. No assembly conflict.

Bug Three. Certificate auth uses a completely different token acquisition path. The token cache bug in SDK v2.34 only affects the DeviceCodeCredential flow. Cert auth bypasses it entirely.

Additional benefits over device code auth:

  • No interactive prompts or browser windows
  • No device codes to copy and paste
  • Scripts run fully unattended and can be scheduled
  • Connection order does not matter on PowerShell 7
  • Works on PowerShell 5.1 when Graph connects first

setting up certificate authentication

You need an Entra ID app registration with the following Microsoft Graph API permissions granted as application permissions, not delegated:

  • Directory.Read.All
  • User.Read.All
  • Policy.Read.All
  • AuditLog.Read.All
  • DeviceManagementConfiguration.Read.All
  • DeviceManagementApps.Read.All
  • Application.Read.All

The app registration also needs the Exchange Administrator role assigned at the tenant level via Entra ID roles.

Create a self-signed certificate and upload the public key to the app registration. Store the certificate in your local Windows certificate store and reference it by thumbprint when connecting.

A full step by step setup guide with PowerShell commands for certificate creation, app registration, and permission assignment is included with the AroraMSP M365 Audit Toolkit.

key takeaways

  • PowerShell 5.1 cannot run Graph SDK and Exchange Online V3 together with device code auth in any connection order.
  • PowerShell 7 device code auth connects successfully but Graph cmdlets fail due to confirmed SDK bug #3495 in v2.34 and later.
  • Certificate based app-only auth on PowerShell 7 works reliably in any connection order.
  • On PowerShell 5.1 with cert auth, Graph must connect before Exchange Online.
  • Upgrade to PowerShell 7 if you are still running M365 automation on PowerShell 5.1.

further reading

Running into authentication issues with your own M365 PowerShell scripts? The AroraMSP M365 Audit Toolkit uses certificate based app-only authentication by design, eliminating all three failure modes documented in this post. View the toolkit at aroramsp.com/whatido or book a free 30-minute call to discuss your environment.
← all posts // himanshu @ aroramsp