From 06c5b3876bb05fd0ba5fa6d64954a3669cee94af Mon Sep 17 00:00:00 2001 From: Chris Miller Date: Thu, 19 Feb 2026 14:39:13 -0500 Subject: [PATCH 1/2] Respect the environment variable when attempting to launch URLs --- src/MSALWrapper/PCAWrapper.cs | 50 ++++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/src/MSALWrapper/PCAWrapper.cs b/src/MSALWrapper/PCAWrapper.cs index 0cb22ed7..e4ddd71e 100644 --- a/src/MSALWrapper/PCAWrapper.cs +++ b/src/MSALWrapper/PCAWrapper.cs @@ -5,7 +5,9 @@ namespace Microsoft.Authentication.MSALWrapper { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Linq; + using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; @@ -83,14 +85,24 @@ public async Task GetTokenSilentAsync(IEnumerable scopes, I /// public async Task GetTokenInteractiveAsync(IEnumerable scopes, IAccount account, CancellationToken cancellationToken) { - AuthenticationResult result = await this.pca + var builder = this.pca .AcquireTokenInteractive(scopes) .WithEmbeddedWebViewOptions(new EmbeddedWebViewOptions() { Title = this.PromptHint, }) .WithUseEmbeddedWebView(this.UseEmbeddedWebView) - .WithAccount(account) + .WithAccount(account); + + if (!this.UseEmbeddedWebView && RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + builder = builder.WithSystemWebViewOptions(new SystemWebViewOptions + { + OpenBrowserAsync = OpenBrowserOnLinuxAsync, + }); + } + + AuthenticationResult result = await builder .ExecuteAsync(cancellationToken) .ConfigureAwait(false); return this.TokenResultOrNull(result); @@ -99,14 +111,24 @@ public async Task GetTokenInteractiveAsync(IEnumerable scop /// public async Task GetTokenInteractiveAsync(IEnumerable scopes, string claims, CancellationToken cancellationToken) { - AuthenticationResult result = await this.pca + var builder = this.pca .AcquireTokenInteractive(scopes) .WithEmbeddedWebViewOptions(new EmbeddedWebViewOptions() { Title = this.PromptHint, }) .WithUseEmbeddedWebView(this.UseEmbeddedWebView) - .WithClaims(claims) + .WithClaims(claims); + + if (!this.UseEmbeddedWebView && RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + builder = builder.WithSystemWebViewOptions(new SystemWebViewOptions + { + OpenBrowserAsync = OpenBrowserOnLinuxAsync, + }); + } + + AuthenticationResult result = await builder .ExecuteAsync(cancellationToken) .ConfigureAwait(false); return this.TokenResultOrNull(result); @@ -164,6 +186,26 @@ public async Task RemoveAsync(IAccount account) await this.pca.RemoveAsync(account); } + private static Task OpenBrowserOnLinuxAsync(Uri uri) + { + string browser = Environment.GetEnvironmentVariable("BROWSER"); + if (!string.IsNullOrEmpty(browser)) + { + Process.Start(new ProcessStartInfo(browser, uri.AbsoluteUri) + { + UseShellExecute = false, + }); + return Task.CompletedTask; + } + + // $BROWSER not set — use default .NET behavior (UseShellExecute tries xdg-open etc.) + Process.Start(new ProcessStartInfo(uri.AbsoluteUri) + { + UseShellExecute = true, + }); + return Task.CompletedTask; + } + private TokenResult TokenResultOrNull(AuthenticationResult result) { if (result == null || string.IsNullOrEmpty(result.AccessToken)) From 68f42f83bbf406a1253de9da8e2b19e9d4186800 Mon Sep 17 00:00:00 2001 From: Chris Miller Date: Mon, 23 Feb 2026 14:06:32 -0500 Subject: [PATCH 2/2] Adjust comment to retrigger pipeline --- src/MSALWrapper/PCAWrapper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MSALWrapper/PCAWrapper.cs b/src/MSALWrapper/PCAWrapper.cs index e4ddd71e..2e3c8185 100644 --- a/src/MSALWrapper/PCAWrapper.cs +++ b/src/MSALWrapper/PCAWrapper.cs @@ -198,7 +198,7 @@ private static Task OpenBrowserOnLinuxAsync(Uri uri) return Task.CompletedTask; } - // $BROWSER not set — use default .NET behavior (UseShellExecute tries xdg-open etc.) + // $BROWSER not set — fall back to default .NET behavior (UseShellExecute tries xdg-open etc.) Process.Start(new ProcessStartInfo(uri.AbsoluteUri) { UseShellExecute = true,