-
Notifications
You must be signed in to change notification settings - Fork 10
Description
a365 setup blueprint fails on macOS 15.x with a PlatformNotSupportedException even after PR #290
introduced a device code fallback for browser auth failures. The fix in #290 only patched
AuthenticationService.AuthenticateInteractivelyAsync, but BlueprintSubcommand has two separate
authentication paths that bypass AuthenticationService entirely and directly use MsalBrowserCredential
without any device code fallback.
Symptoms
The user sees the following in the output before the command fails:
IMPORTANT: You must grant consent for all required permissions.
Successfully authenticated to Microsoft Graph!
Successfully authenticated to Microsoft Graph
Opening browser for authentication...
WARNING: Browser authentication is not supported on this platform: macOS 15.3.1
WARNING: Could not retrieve current user for sponsors field: Browser authentication is not supported on this platform (macOS 15.3.1)
Opening browser for authentication...
WARNING: Browser authentication is not supported on this platform: macOS 15.3.1
ERROR: Failed to acquire MSAL Graph access token
ERROR: Failed to extract access token from Graph client
ERROR: Failed to create agent blueprint
ERROR: Microsoft Graph API operation failed: Create Agent Blueprint
Blueprint creation failed.
Root Cause
PR #290 added the PlatformNotSupportedException → device code fallback inside
AuthenticationService.AuthenticateInteractivelyAsync. However, BlueprintSubcommand has two
authentication paths that never call AuthenticationService:
Gap 1 — AcquireMsalGraphTokenAsync (no fallback)
BlueprintSubcommand.AcquireMsalGraphTokenAsync creates MsalBrowserCredential and calls
GetTokenAsync directly. When MSAL throws PlatformNotSupportedException on macOS, it is
wrapped as MsalAuthenticationFailedException by MsalBrowserCredential, but the caller only
has a generic catch (Exception) that logs the error and returns null. There is no fallback
to device code flow.
Gap 2 — InteractiveGraphAuthService + lazy token acquisition
BlueprintSubcommand.GetAuthenticatedGraphClientAsync delegates to InteractiveGraphAuthService,
which creates a MsalBrowserCredential and passes it to the GraphServiceClient constructor.
The critical issue: GraphServiceClient acquires tokens lazily — only when the first actual
Graph API call is made. The GraphServiceClient constructor always succeeds, which causes
InteractiveGraphAuthService to log "Successfully authenticated to Microsoft Graph!" prematurely
and return a client backed by a non-functional credential.
The try/catch block in InteractiveGraphAuthService.GetAuthenticatedGraphClientAsync never fires
for PlatformNotSupportedException because the exception surfaces later, from inside the Graph SDK,
when an API call is attempted. At that point there is no recovery path — the credential is already
baked into the GraphServiceClient instance with no fallback.
This is also a code duplication problem: the device code fallback logic exists in
AuthenticationService but must now be replicated (or properly centralized) for every code path
that uses MsalBrowserCredential directly.
Affected Files
| File | Issue |
|---|---|
Commands/SetupSubcommands/BlueprintSubcommand.cs |
AcquireMsalGraphTokenAsync — no device code fallback |
Services/InteractiveGraphAuthService.cs |
No device code fallback; eagerly logs success before token is acquired |
Fix
Fix 1 — AcquireMsalGraphTokenAsync
Add a catch for MsalAuthenticationFailedException with inner PlatformNotSupportedException.
On macOS (or any platform where browser auth is unsupported), fall back to DeviceCodeCredential
using the same clientAppId and tenantId.
Fix 2 — InteractiveGraphAuthService.GetAuthenticatedGraphClientAsync
Before constructing the GraphServiceClient, eagerly acquire a token with MsalBrowserCredential
to detect platform support at construction time. If MsalAuthenticationFailedException with inner
PlatformNotSupportedException is caught, fall back to DeviceCodeCredential and build the
GraphServiceClient with that credential instead. This ensures the "Successfully authenticated"
log only appears after authentication has actually succeeded.
Related
- PR fix: fall back to device code when browser auth fails on macOS #290 — fix: fall back to device code when browser auth fails on macOS (partial fix)
- Issue a365 setup all fails on macOS 15.x with PlatformNotSupportedException during authentication #291 — original macOS 15.x auth failure report