@@ -5,7 +5,9 @@ namespace Microsoft.Authentication.MSALWrapper
55{
66 using System ;
77 using System . Collections . Generic ;
8+ using System . Diagnostics ;
89 using System . Linq ;
10+ using System . Runtime . InteropServices ;
911 using System . Threading ;
1012 using System . Threading . Tasks ;
1113
@@ -83,14 +85,24 @@ public async Task<TokenResult> GetTokenSilentAsync(IEnumerable<string> scopes, I
8385 /// <inheritdoc/>
8486 public async Task < TokenResult > GetTokenInteractiveAsync ( IEnumerable < string > scopes , IAccount account , CancellationToken cancellationToken )
8587 {
86- AuthenticationResult result = await this . pca
88+ var builder = this . pca
8789 . AcquireTokenInteractive ( scopes )
8890 . WithEmbeddedWebViewOptions ( new EmbeddedWebViewOptions ( )
8991 {
9092 Title = this . PromptHint ,
9193 } )
9294 . WithUseEmbeddedWebView ( this . UseEmbeddedWebView )
93- . WithAccount ( account )
95+ . WithAccount ( account ) ;
96+
97+ if ( ! this . UseEmbeddedWebView && RuntimeInformation . IsOSPlatform ( OSPlatform . Linux ) )
98+ {
99+ builder = builder . WithSystemWebViewOptions ( new SystemWebViewOptions
100+ {
101+ OpenBrowserAsync = OpenBrowserOnLinuxAsync ,
102+ } ) ;
103+ }
104+
105+ AuthenticationResult result = await builder
94106 . ExecuteAsync ( cancellationToken )
95107 . ConfigureAwait ( false ) ;
96108 return this . TokenResultOrNull ( result ) ;
@@ -99,14 +111,24 @@ public async Task<TokenResult> GetTokenInteractiveAsync(IEnumerable<string> scop
99111 /// <inheritdoc/>
100112 public async Task < TokenResult > GetTokenInteractiveAsync ( IEnumerable < string > scopes , string claims , CancellationToken cancellationToken )
101113 {
102- AuthenticationResult result = await this . pca
114+ var builder = this . pca
103115 . AcquireTokenInteractive ( scopes )
104116 . WithEmbeddedWebViewOptions ( new EmbeddedWebViewOptions ( )
105117 {
106118 Title = this . PromptHint ,
107119 } )
108120 . WithUseEmbeddedWebView ( this . UseEmbeddedWebView )
109- . WithClaims ( claims )
121+ . WithClaims ( claims ) ;
122+
123+ if ( ! this . UseEmbeddedWebView && RuntimeInformation . IsOSPlatform ( OSPlatform . Linux ) )
124+ {
125+ builder = builder . WithSystemWebViewOptions ( new SystemWebViewOptions
126+ {
127+ OpenBrowserAsync = OpenBrowserOnLinuxAsync ,
128+ } ) ;
129+ }
130+
131+ AuthenticationResult result = await builder
110132 . ExecuteAsync ( cancellationToken )
111133 . ConfigureAwait ( false ) ;
112134 return this . TokenResultOrNull ( result ) ;
@@ -164,6 +186,26 @@ public async Task RemoveAsync(IAccount account)
164186 await this . pca . RemoveAsync ( account ) ;
165187 }
166188
189+ private static Task OpenBrowserOnLinuxAsync ( Uri uri )
190+ {
191+ string browser = Environment . GetEnvironmentVariable ( "BROWSER" ) ;
192+ if ( ! string . IsNullOrEmpty ( browser ) )
193+ {
194+ Process . Start ( new ProcessStartInfo ( browser , uri . AbsoluteUri )
195+ {
196+ UseShellExecute = false ,
197+ } ) ;
198+ return Task . CompletedTask ;
199+ }
200+
201+ // $BROWSER not set — fall back to default .NET behavior (UseShellExecute tries xdg-open etc.)
202+ Process . Start ( new ProcessStartInfo ( uri . AbsoluteUri )
203+ {
204+ UseShellExecute = true ,
205+ } ) ;
206+ return Task . CompletedTask ;
207+ }
208+
167209 private TokenResult TokenResultOrNull ( AuthenticationResult result )
168210 {
169211 if ( result == null || string . IsNullOrEmpty ( result . AccessToken ) )
0 commit comments