diff --git a/sandbox/OpenIddict.Sandbox.WinForms.Client/Worker.cs b/sandbox/OpenIddict.Sandbox.WinForms.Client/Worker.cs
index 6bfca1b3..27027265 100644
--- a/sandbox/OpenIddict.Sandbox.WinForms.Client/Worker.cs
+++ b/sandbox/OpenIddict.Sandbox.WinForms.Client/Worker.cs
@@ -27,7 +27,7 @@ public class Worker : IHostedService
// in HKEY_CLASSES_ROOT (in this case, it should be added by a dedicated installer).
//
// Alternatively, the application can be packaged and use windows.protocol to
- // register the protocol handler/custom URI scheme with the operation system.
+ // register the protocol handler/custom URI scheme with the operating system.
using var root = Registry.CurrentUser.CreateSubKey("SOFTWARE\\Classes\\com.openiddict.sandbox.winforms.client");
root.SetValue(string.Empty, "URL:com.openiddict.sandbox.winforms.client");
root.SetValue("URL Protocol", string.Empty);
diff --git a/sandbox/OpenIddict.Sandbox.Wpf.Client/Worker.cs b/sandbox/OpenIddict.Sandbox.Wpf.Client/Worker.cs
index 0f65a8d5..b4d21290 100644
--- a/sandbox/OpenIddict.Sandbox.Wpf.Client/Worker.cs
+++ b/sandbox/OpenIddict.Sandbox.Wpf.Client/Worker.cs
@@ -27,7 +27,7 @@ public class Worker : IHostedService
// in HKEY_CLASSES_ROOT (in this case, it should be added by a dedicated installer).
//
// Alternatively, the application can be packaged and use windows.protocol to
- // register the protocol handler/custom URI scheme with the operation system.
+ // register the protocol handler/custom URI scheme with the operating system.
using var root = Registry.CurrentUser.CreateSubKey("SOFTWARE\\Classes\\com.openiddict.sandbox.wpf.client");
root.SetValue(string.Empty, "URL:com.openiddict.sandbox.wpf.client");
root.SetValue("URL Protocol", string.Empty);
diff --git a/src/OpenIddict.Abstractions/OpenIddictResources.resx b/src/OpenIddict.Abstractions/OpenIddictResources.resx
index b2fff355..13f41e47 100644
--- a/src/OpenIddict.Abstractions/OpenIddictResources.resx
+++ b/src/OpenIddict.Abstractions/OpenIddictResources.resx
@@ -1560,7 +1560,7 @@ To apply post-logout redirection responses, create a class implementing 'IOpenId
An explicit grant type must be attached when specifying a specific response type (except when using the special response_type=none value).
- AS web authentication sessions are only supported on iOS 12.0+/macOS 10.15+/Mac Catalyst 12.0+ and require using an OS-specific target framework moniker (e.g on macOS, 'net8.0-macos15.0').
+ AS web authentication sessions are only supported on iOS 12.0+/macOS 10.15+/Mac Catalyst 12.0+ and require using an OS-specific target framework moniker on macOS (e.g 'net8.0-macos15.0').
The current UI window cannot be resolved.
@@ -1569,8 +1569,7 @@ To apply post-logout redirection responses, create a class implementing 'IOpenId
An unknown error occurred while trying to start an AS web authentication session.
- The generic version of the OpenIddict.Client.SystemIntegration package cannot be used on this platform. Make sure your application is referencing the correct version by using the appropriate OS-specific TFM (e.g on macOS, 'net8.0-macos10.15').
- This resource is no longer used and will be removed in a future version.
+ The portable version of the OpenIddict.Client.SystemIntegration package cannot be used on Android, iOS and Mac Catalyst. Make sure your application is referencing the correct version by using the appropriate OS-specific TFM (e.g on iOS, 'net8.0-ios18.0').
An HTTP redirect_uri or post_logout_redirect_uri cannot be used when using AS web authentication sessions. Make sure you're using a custom protocol scheme for all the callback URIs attached to the client registration. Alternatively, you can register an associated domain and use an HTTPS redirect_uri or post_logout_redirect_uri pointing to that domain (supported only on iOS 17.4+, Mac Catalyst 17.4+ and macOS 14.4+).
@@ -1579,7 +1578,7 @@ To apply post-logout redirection responses, create a class implementing 'IOpenId
The Zoho integration requires sending the region of the server when using the client credentials or refresh token grants. For that, attach a ".location" authentication property containing the region to use.
- Custom tabs intents are only supported on Android and require using an OS-specific target framework moniker (e.g 'net8.0-android34.0').
+ Custom tabs intents are only supported on Android.
The specified intent doesn't contain a valid data URI.
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationBuilder.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationBuilder.cs
index f3cac42e..866b0742 100644
--- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationBuilder.cs
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationBuilder.cs
@@ -121,7 +121,7 @@ public sealed class OpenIddictClientSystemIntegrationBuilder
/// The .
public OpenIddictClientSystemIntegrationBuilder SetAllowedEmbeddedWebServerPorts(params int[] ports)
{
- if (Array.Exists(ports, static port => port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort))
+ if (Array.Exists(ports, static port => port is < IPEndPoint.MinPort or > IPEndPoint.MaxPort))
{
throw new ArgumentOutOfRangeException(nameof(ports));
}
@@ -278,25 +278,15 @@ public sealed class OpenIddictClientSystemIntegrationBuilder
return Configure(options => options.PipeSecurity = security);
}
- ///
- /// Determines whether the specified object is equal to the current object.
- ///
- /// The object to compare with the current object.
- /// if the specified object is equal to the current object; otherwise, false.
+ ///
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals(object? obj) => base.Equals(obj);
- ///
- /// Serves as the default hash function.
- ///
- /// A hash code for the current object.
+ ///
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode() => base.GetHashCode();
- ///
- /// Returns a string that represents the current object.
- ///
- /// A string that represents the current object.
+ ///
[EditorBrowsable(EditorBrowsableState.Never)]
public override string? ToString() => base.ToString();
}
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationConfiguration.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationConfiguration.cs
index c8c7287a..f86430d1 100644
--- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationConfiguration.cs
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationConfiguration.cs
@@ -83,6 +83,25 @@ public sealed class OpenIddictClientSystemIntegrationConfiguration : IConfigureO
throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0389));
}
+#if !SUPPORTS_ANDROID
+ // When running on Android, iOS or Mac Catalyst, ensure the version compiled for these platforms
+ // is used to prevent the generic/non-OS specific TFM from being used as launching the system
+ // browser cannot be done using Process.Start() and requires using OS-specific APIs that are
+ // not available on the portable version of the OpenIddict.Client.SystemIntegration package.
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("android")))
+ {
+ throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0449));
+ }
+#endif
+
+#if !SUPPORTS_UIKIT
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("ios")) ||
+ RuntimeInformation.IsOSPlatform(OSPlatform.Create("maccatalyst")))
+ {
+ throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0449));
+ }
+#endif
+
#if SUPPORTS_OPERATING_SYSTEM_VERSIONS_COMPARISON
// Ensure the operating system version is supported.
if ((OperatingSystem.IsAndroid() && !OperatingSystem.IsAndroidVersionAtLeast(21)) ||
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationExtensions.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationExtensions.cs
index 708bd6bf..bb83a7fe 100644
--- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationExtensions.cs
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationExtensions.cs
@@ -42,6 +42,25 @@ public static class OpenIddictClientSystemIntegrationExtensions
throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0389));
}
+#if !SUPPORTS_ANDROID
+ // When running on Android, iOS or Mac Catalyst, ensure the version compiled for these platforms
+ // is used to prevent the generic/non-OS specific TFM from being used as launching the system
+ // browser cannot be done using Process.Start() and requires using OS-specific APIs that are
+ // not available on the portable version of the OpenIddict.Client.SystemIntegration package.
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("android")))
+ {
+ throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0449));
+ }
+#endif
+
+#if !SUPPORTS_UIKIT
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("ios")) ||
+ RuntimeInformation.IsOSPlatform(OSPlatform.Create("maccatalyst")))
+ {
+ throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0449));
+ }
+#endif
+
#if SUPPORTS_OPERATING_SYSTEM_VERSIONS_COMPARISON
// Ensure the operating system version is supported.
if ((OperatingSystem.IsAndroid() && !OperatingSystem.IsAndroidVersionAtLeast(21)) ||
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Authentication.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Authentication.cs
index c59cb672..8dbae893 100644
--- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Authentication.cs
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Authentication.cs
@@ -5,7 +5,6 @@
*/
using System.Collections.Immutable;
-using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
@@ -106,8 +105,6 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
throw new ArgumentNullException(nameof(context));
}
- Debug.Assert(context.Transaction.Request is not null, SR.GetResourceString(SR.ID4008));
-
#if SUPPORTS_AUTHENTICATION_SERVICES && SUPPORTS_FOUNDATION
if (string.IsNullOrEmpty(context.RedirectUri) ||
!Uri.TryCreate(context.RedirectUri, UriKind.Absolute, out Uri? uri))
@@ -239,7 +236,7 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
NSUrl CreateUrl() => new(OpenIddictHelpers.AddQueryStringParameters(
uri: new Uri(context.AuthorizationEndpoint, UriKind.Absolute),
- parameters: context.Transaction.Request.GetParameters().ToDictionary(
+ parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key,
static parameter => (StringValues) parameter.Value)).AbsoluteUri);
@@ -331,8 +328,6 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
throw new ArgumentNullException(nameof(context));
}
- Debug.Assert(context.Transaction.Request is not null, SR.GetResourceString(SR.ID4008));
-
#if SUPPORTS_ANDROID && SUPPORTS_ANDROIDX_BROWSER
if (string.IsNullOrEmpty(context.RedirectUri))
{
@@ -359,7 +354,7 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
// custom activity responsible for handling callback URIs pointing to a custom scheme.
intent.LaunchUrl(Application.Context, NativeUri.Parse(OpenIddictHelpers.AddQueryStringParameters(
uri: new Uri(context.AuthorizationEndpoint, UriKind.Absolute),
- parameters: context.Transaction.Request.GetParameters().ToDictionary(
+ parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key,
static parameter => (StringValues) parameter.Value)).AbsoluteUri)!);
@@ -404,8 +399,6 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
throw new ArgumentNullException(nameof(context));
}
- Debug.Assert(context.Transaction.Request is not null, SR.GetResourceString(SR.ID4008));
-
#if SUPPORTS_WINDOWS_RUNTIME
if (string.IsNullOrEmpty(context.RedirectUri))
{
@@ -444,7 +437,7 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
options : WebAuthenticationOptions.None,
requestUri : OpenIddictHelpers.AddQueryStringParameters(
uri: new Uri(context.AuthorizationEndpoint, UriKind.Absolute),
- parameters: context.Transaction.Request.GetParameters().ToDictionary(
+ parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key,
static parameter => (StringValues) parameter.Value)),
callbackUri: new Uri(context.RedirectUri, UriKind.Absolute)))
@@ -551,11 +544,9 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
throw new ArgumentNullException(nameof(context));
}
- Debug.Assert(context.Transaction.Request is not null, SR.GetResourceString(SR.ID4008));
-
var uri = OpenIddictHelpers.AddQueryStringParameters(
uri: new Uri(context.AuthorizationEndpoint, UriKind.Absolute),
- parameters: context.Transaction.Request.GetParameters().ToDictionary(
+ parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key,
static parameter => (StringValues) parameter.Value));
@@ -594,6 +585,8 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
}
}
+ // On Android, iOS and Mac Catalyst, Process.Start() is not supported and
+ // OS-specific/non-portable APIs must be used to launch the system browser.
#if SUPPORTS_ANDROID
if (OperatingSystem.IsAndroid() && TryLaunchBrowserWithGenericIntent(uri))
{
@@ -601,20 +594,26 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
return;
}
#endif
-
#if SUPPORTS_UIKIT
if ((OperatingSystem.IsIOS() || OperatingSystem.IsMacCatalyst()) && await TryLaunchBrowserWithUIApplicationAsync(uri))
{
context.HandleRequest();
return;
}
-#elif SUPPORTS_APPKIT
+#endif
+#if SUPPORTS_APPKIT
if (OperatingSystem.IsMacOS() && TryLaunchBrowserWithNSWorkspace(uri))
{
context.HandleRequest();
return;
}
#endif
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && await TryLaunchBrowserWithOpenAsync(uri))
+ {
+ context.HandleRequest();
+ return;
+ }
+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && await TryLaunchBrowserWithXdgOpenAsync(uri))
{
context.HandleRequest();
@@ -650,8 +649,6 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
throw new ArgumentNullException(nameof(context));
}
- Debug.Assert(context.Transaction.Response is not null, SR.GetResourceString(SR.ID4007));
-
// This handler only applies to HTTP listener requests. If the HTTP context cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var response = context.Transaction.GetHttpListenerContext()?.Response ??
@@ -663,7 +660,7 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
// Return a message indicating whether the authentication process
// succeeded or failed and that will be visible by the user.
- var buffer = Encoding.UTF8.GetBytes(context.Transaction.Response.Error switch
+ var buffer = Encoding.UTF8.GetBytes(context.Response.Error switch
{
null or { Length: 0 } => "Login completed. Please return to the application.",
Errors.AccessDenied => "Authorization denied. Please return to the application.",
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs
index 8a9d04cb..0600593a 100644
--- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs
@@ -5,7 +5,6 @@
*/
using System.Collections.Immutable;
-using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
@@ -106,8 +105,6 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
throw new ArgumentNullException(nameof(context));
}
- Debug.Assert(context.Transaction.Request is not null, SR.GetResourceString(SR.ID4008));
-
#if SUPPORTS_AUTHENTICATION_SERVICES && SUPPORTS_FOUNDATION
if (string.IsNullOrEmpty(context.PostLogoutRedirectUri) ||
!Uri.TryCreate(context.PostLogoutRedirectUri, UriKind.Absolute, out Uri? uri))
@@ -239,7 +236,7 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
NSUrl CreateUrl() => new(OpenIddictHelpers.AddQueryStringParameters(
uri: new Uri(context.EndSessionEndpoint, UriKind.Absolute),
- parameters: context.Transaction.Request.GetParameters().ToDictionary(
+ parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key,
static parameter => (StringValues) parameter.Value)).AbsoluteUri);
@@ -331,8 +328,6 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
throw new ArgumentNullException(nameof(context));
}
- Debug.Assert(context.Transaction.Request is not null, SR.GetResourceString(SR.ID4008));
-
#if SUPPORTS_ANDROID && SUPPORTS_ANDROIDX_BROWSER
if (string.IsNullOrEmpty(context.PostLogoutRedirectUri))
{
@@ -359,7 +354,7 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
// custom activity responsible for handling callback URIs pointing to a custom scheme.
intent.LaunchUrl(Application.Context, NativeUri.Parse(OpenIddictHelpers.AddQueryStringParameters(
uri: new Uri(context.EndSessionEndpoint, UriKind.Absolute),
- parameters: context.Transaction.Request.GetParameters().ToDictionary(
+ parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key,
static parameter => (StringValues) parameter.Value)).AbsoluteUri)!);
@@ -404,8 +399,6 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
throw new ArgumentNullException(nameof(context));
}
- Debug.Assert(context.Transaction.Request is not null, SR.GetResourceString(SR.ID4008));
-
#if SUPPORTS_WINDOWS_RUNTIME
if (string.IsNullOrEmpty(context.PostLogoutRedirectUri))
{
@@ -444,7 +437,7 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
options : WebAuthenticationOptions.None,
requestUri : OpenIddictHelpers.AddQueryStringParameters(
uri: new Uri(context.EndSessionEndpoint, UriKind.Absolute),
- parameters: context.Transaction.Request.GetParameters().ToDictionary(
+ parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key,
static parameter => (StringValues) parameter.Value)),
callbackUri: new Uri(context.PostLogoutRedirectUri, UriKind.Absolute)))
@@ -551,11 +544,9 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
throw new ArgumentNullException(nameof(context));
}
- Debug.Assert(context.Transaction.Request is not null, SR.GetResourceString(SR.ID4008));
-
var uri = OpenIddictHelpers.AddQueryStringParameters(
uri: new Uri(context.EndSessionEndpoint, UriKind.Absolute),
- parameters: context.Transaction.Request.GetParameters().ToDictionary(
+ parameters: context.Request.GetParameters().ToDictionary(
static parameter => parameter.Key,
static parameter => (StringValues) parameter.Value));
@@ -594,6 +585,8 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
}
}
+ // On Android, iOS and Mac Catalyst, Process.Start() is not supported and
+ // OS-specific/non-portable APIs must be used to launch the system browser.
#if SUPPORTS_ANDROID
if (OperatingSystem.IsAndroid() && TryLaunchBrowserWithGenericIntent(uri))
{
@@ -601,20 +594,26 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
return;
}
#endif
-
#if SUPPORTS_UIKIT
if ((OperatingSystem.IsIOS() || OperatingSystem.IsMacCatalyst()) && await TryLaunchBrowserWithUIApplicationAsync(uri))
{
context.HandleRequest();
return;
}
-#elif SUPPORTS_APPKIT
+#endif
+#if SUPPORTS_APPKIT
if (OperatingSystem.IsMacOS() && TryLaunchBrowserWithNSWorkspace(uri))
{
context.HandleRequest();
return;
}
#endif
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && await TryLaunchBrowserWithOpenAsync(uri))
+ {
+ context.HandleRequest();
+ return;
+ }
+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && await TryLaunchBrowserWithXdgOpenAsync(uri))
{
context.HandleRequest();
@@ -650,8 +649,6 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
throw new ArgumentNullException(nameof(context));
}
- Debug.Assert(context.Transaction.Response is not null, SR.GetResourceString(SR.ID4007));
-
// This handler only applies to HTTP listener requests. If the HTTP context cannot be resolved,
// this may indicate that the request was incorrectly processed by another server stack.
var response = context.Transaction.GetHttpListenerContext()?.Response ??
@@ -663,7 +660,7 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
// Return a message indicating whether the sign-out process
// succeeded or failed and that will be visible by the user.
- var buffer = Encoding.UTF8.GetBytes(context.Transaction.Response.Error switch
+ var buffer = Encoding.UTF8.GetBytes(context.Response.Error switch
{
null or { Length: 0 } => "Logout completed. Please return to the application.",
Errors.AccessDenied => "Logout denied. Please return to the application.",
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHelpers.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHelpers.cs
index a0e9f69a..f46cdf14 100644
--- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHelpers.cs
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHelpers.cs
@@ -400,11 +400,10 @@ public static class OpenIddictClientSystemIntegrationHelpers
};
///
- /// Starts the system browser using ShellExecute.
+ /// Starts the system browser using the operating system shell.
///
/// The to use.
/// if the browser could be started, otherwise.
- [SupportedOSPlatform("linux")]
[SupportedOSPlatform("windows")]
internal static async ValueTask TryLaunchBrowserWithShellExecuteAsync(Uri uri)
{
@@ -501,7 +500,40 @@ public static class OpenIddictClientSystemIntegrationHelpers
#endif
///
- /// Starts the system browser using xdg-open.
+ /// Starts the system browser using the "open" executable.
+ ///
+ /// The to use.
+ /// if the browser could be started, otherwise.
+ [SupportedOSPlatform("macos")]
+ internal static async ValueTask TryLaunchBrowserWithOpenAsync(Uri uri)
+ {
+ try
+ {
+ await Task.Run(() => Process.Start(new ProcessStartInfo
+ {
+ FileName = "/usr/bin/open",
+ Arguments = uri.AbsoluteUri,
+ UseShellExecute = false,
+
+ // Note: children processes always inherit the standard input/output/error handles of the
+ // parent process by default. To ensure the messages logged by the system browser are not
+ // written to the stdio/stderr of the current process, the streams are always redirected.
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ RedirectStandardOutput = true
+ }));
+
+ return true;
+ }
+
+ catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Starts the system browser using the "xdg-open" executable.
///
/// The to use.
/// if the browser could be started, otherwise.
@@ -516,9 +548,9 @@ public static class OpenIddictClientSystemIntegrationHelpers
Arguments = uri.AbsoluteUri,
UseShellExecute = false,
- // Note: on some Linux distributions, xdg-open is known to propagate errors
- // and warnings written to the standard error stream to the parent process.
- // To avoid that, the streams are redirected to this instance and ignored.
+ // Note: children processes always inherit the standard input/output/error handles of the
+ // parent process by default. To ensure the messages logged by the system browser are not
+ // written to the stdio/stderr of the current process, the streams are always redirected.
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true
@@ -527,7 +559,7 @@ public static class OpenIddictClientSystemIntegrationHelpers
return true;
}
- catch (UnauthorizedAccessException)
+ catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
return false;
}
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHttpListener.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHttpListener.cs
index 98fcc88c..aa88c4b4 100644
--- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHttpListener.cs
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHttpListener.cs
@@ -116,7 +116,7 @@ public sealed class OpenIddictClientSystemIntegrationHttpListener : BackgroundSe
Stack? exceptions = null;
- for (var port = IPEndPoint.MinPort; port <= IPEndPoint.MaxPort; port++)
+ for (var port = IPEndPoint.MinPort; port is <= IPEndPoint.MaxPort; port++)
{
cancellationToken.ThrowIfCancellationRequested();