diff --git a/src/OpenIddict.Abstractions/OpenIddictResources.resx b/src/OpenIddict.Abstractions/OpenIddictResources.resx
index ee1731394..a1f5c4488 100644
--- a/src/OpenIddict.Abstractions/OpenIddictResources.resx
+++ b/src/OpenIddict.Abstractions/OpenIddictResources.resx
@@ -1480,7 +1480,7 @@ To apply post-logout redirection responses, create a class implementing 'IOpenId
The web authentication broker is only supported on UWP and requires running Windows 10 version 1709 (Fall Creators) or higher.
- The web authentication result cannot be resolved or contains invalid data.
+ The platform callback cannot be resolved or contains invalid data.
The issuer attached to the static configuration must be the same as the one configured in the validation options.
@@ -1692,6 +1692,9 @@ To apply post-logout redirection responses, create a class implementing 'IOpenId
Custom tabs intents are only supported on Android.
+
+ The specified intent doesn't contain a valid data URI.
+
The security token is missing.
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationExtensions.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationExtensions.cs
index b076e3800..123e4dcea 100644
--- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationExtensions.cs
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationExtensions.cs
@@ -103,17 +103,18 @@ public static OpenIddictClientSystemIntegrationBuilder UseSystemIntegration(this
// Register the built-in filters used by the default OpenIddict client system integration event handlers.
builder.Services.TryAddSingleton();
- builder.Services.TryAddSingleton();
builder.Services.TryAddSingleton();
builder.Services.TryAddSingleton();
- builder.Services.TryAddSingleton();
builder.Services.TryAddSingleton();
builder.Services.TryAddSingleton();
builder.Services.TryAddSingleton();
+ builder.Services.TryAddSingleton();
builder.Services.TryAddSingleton();
builder.Services.TryAddSingleton();
builder.Services.TryAddSingleton();
+#pragma warning disable CS0618
builder.Services.TryAddSingleton();
+#pragma warning restore CS0618
// Register the built-in event handlers used by the OpenIddict client system integration components.
// Note: the order used here is not important, as the actual order is set in the options.
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlerFilters.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlerFilters.cs
index 6d809c25f..dab17af12 100644
--- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlerFilters.cs
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlerFilters.cs
@@ -17,34 +17,6 @@ namespace OpenIddict.Client.SystemIntegration;
[EditorBrowsable(EditorBrowsableState.Advanced)]
public static class OpenIddictClientSystemIntegrationHandlerFilters
{
- ///
- /// Represents a filter that excludes the associated handlers if no AS web
- /// authentication callback URL can be found in the transaction properties.
- ///
- public sealed class RequireASWebAuthenticationCallbackUrl : IOpenIddictClientHandlerFilter
- {
- ///
- public ValueTask IsActiveAsync(BaseContext context)
- {
- if (context is null)
- {
- throw new ArgumentNullException(nameof(context));
- }
-
-#if SUPPORTS_AUTHENTICATION_SERVICES && SUPPORTS_FOUNDATION
- if (IsASWebAuthenticationSessionSupported())
- {
- return new(ContainsASWebAuthenticationSessionResult(context.Transaction));
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- static bool ContainsASWebAuthenticationSessionResult(OpenIddictClientTransaction transaction)
- => transaction.GetASWebAuthenticationCallbackUrl() is not null;
-#endif
- return new(false);
- }
- }
-
///
/// Represents a filter that excludes the associated handlers if
/// the AS web authentication session integration was not enabled.
@@ -133,33 +105,6 @@ public ValueTask IsActiveAsync(BaseContext context)
return new(false);
}
}
- ///
- /// Represents a filter that excludes the associated handlers if no
- /// custom tabs intent data can be found in the transaction properties.
- ///
- public sealed class RequireCustomTabsIntentData : IOpenIddictClientHandlerFilter
- {
- ///
- public ValueTask IsActiveAsync(BaseContext context)
- {
- if (context is null)
- {
- throw new ArgumentNullException(nameof(context));
- }
-
-#if SUPPORTS_ANDROID && SUPPORTS_ANDROIDX_BROWSER
- if (IsCustomTabsIntentSupported())
- {
- return new(ContainsCustomTabsIntentData(context.Transaction));
- }
-
- [MethodImpl(MethodImplOptions.NoInlining)]
- static bool ContainsCustomTabsIntentData(OpenIddictClientTransaction transaction)
- => transaction.GetCustomTabsIntentData() is not null;
-#endif
- return new(false);
- }
- }
///
/// Represents a filter that excludes the associated handlers if the embedded web server was not enabled.
@@ -217,6 +162,24 @@ public ValueTask IsActiveAsync(BaseContext context)
}
}
+ ///
+ /// Represents a filter that excludes the associated handlers if no
+ /// platform callback can be found in the transaction properties.
+ ///
+ public sealed class RequirePlatformCallback : IOpenIddictClientHandlerFilter
+ {
+ ///
+ public ValueTask IsActiveAsync(BaseContext context)
+ {
+ if (context is null)
+ {
+ throw new ArgumentNullException(nameof(context));
+ }
+
+ return new(context.Transaction.GetPlatformCallback() is not null);
+ }
+ }
+
///
/// Represents a filter that excludes the associated handlers if no protocol activation was found.
///
@@ -304,6 +267,7 @@ public ValueTask IsActiveAsync(BaseContext context)
/// Represents a filter that excludes the associated handlers if no
/// web authentication operation was triggered during the transaction.
///
+ [Obsolete("This filter is obsolete and will be removed in a future version.")]
public sealed class RequireWebAuthenticationResult : IOpenIddictClientHandlerFilter
{
///
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Authentication.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Authentication.cs
index d0adb3935..a77e63abc 100644
--- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Authentication.cs
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Authentication.cs
@@ -57,9 +57,7 @@ public static class Authentication
*/
ExtractGetOrPostHttpListenerRequest.Descriptor,
ExtractProtocolActivationParameters.Descriptor,
- ExtractASWebAuthenticationCallbackUrlData.Descriptor,
- ExtractCustomTabsIntentData.Descriptor,
- ExtractWebAuthenticationResultData.Descriptor,
+ ExtractPlatformCallbackParameters.Descriptor,
/*
* Redirection response handling:
@@ -68,9 +66,7 @@ public static class Authentication
AttachCacheControlHeader.Descriptor,
ProcessEmptyHttpResponse.Descriptor,
ProcessProtocolActivationResponse.Descriptor,
- ProcessASWebAuthenticationSessionResponse.Descriptor,
- ProcessCustomTabsIntentResponse.Descriptor,
- ProcessWebAuthenticationResultResponse.Descriptor
+ ProcessPlatformCallbackResponse.Descriptor
]);
///
@@ -123,7 +119,8 @@ public async ValueTask HandleAsync(ApplyAuthorizationRequestContext context)
throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0446));
}
- var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
+ var source = new TaskCompletionSource(
+ TaskCreationOptions.RunContinuationsAsynchronously);
// OpenIddict represents the complete interactive authentication dance as a two-phase process:
// - The challenge, during which the user is redirected to the authorization server, either
@@ -161,11 +158,11 @@ public async ValueTask HandleAsync(ApplyAuthorizationRequestContext context)
throw new InvalidOperationException(SR.GetResourceString(SR.ID0448));
}
- NSUrl url;
+ OpenIddictClientSystemIntegrationPlatformCallback callback;
try
{
- url = await source.Task.WaitAsync(context.CancellationToken);
+ callback = await source.Task.WaitAsync(context.CancellationToken);
}
// Since the result of this operation is known by the time the task signaled by ASWebAuthenticationSession
@@ -195,7 +192,7 @@ public async ValueTask HandleAsync(ApplyAuthorizationRequestContext context)
return;
}
- await _service.HandleASWebAuthenticationCallbackUrlAsync(url, context.CancellationToken);
+ await _service.HandlePlatformCallbackAsync(callback, context.CancellationToken);
context.HandleRequest();
return;
@@ -250,7 +247,43 @@ void HandleCallback(NSUrl? url, NSError? error)
{
if (url is not null)
{
- source.SetResult(url);
+ var parameters = new Dictionary(StringComparer.Ordinal);
+
+ if (!string.IsNullOrEmpty(url.Query))
+ {
+ foreach (var parameter in OpenIddictHelpers.ParseQuery(url.Query))
+ {
+ parameters[parameter.Key] = parameter.Value.Count switch
+ {
+ 0 => default,
+ 1 => parameter.Value[0],
+ _ => parameter.Value.ToArray()
+ };
+ }
+ }
+
+ // Note: the fragment is always processed after the query string to ensure that
+ // parameters extracted from the fragment are preferred to parameters extracted
+ // from the query string when they are present in both parts.
+
+ if (!string.IsNullOrEmpty(url.Fragment))
+ {
+ foreach (var parameter in OpenIddictHelpers.ParseFragment(url.Fragment))
+ {
+ parameters[parameter.Key] = parameter.Value.Count switch
+ {
+ 0 => default,
+ 1 => parameter.Value[0],
+ _ => parameter.Value.ToArray()
+ };
+ }
+ }
+
+ source.SetResult(new OpenIddictClientSystemIntegrationPlatformCallback(url!, parameters)
+ {
+ // Attach the raw URL to the callback properties.
+ Properties = { [typeof(NSUrl).FullName!] = url }
+ });
}
else if (error is not null)
@@ -426,8 +459,47 @@ public async ValueTask HandleAsync(ApplyAuthorizationRequestContext context)
parameter => new StringValues((string?[]?) parameter.Value))),
callbackUri: new Uri(context.RedirectUri, UriKind.Absolute)))
{
- case { ResponseStatus: WebAuthenticationStatus.Success } result:
- await _service.HandleWebAuthenticationResultAsync(result, context.CancellationToken);
+ case { ResponseStatus: WebAuthenticationStatus.Success } result
+ when Uri.TryCreate(result.ResponseData, UriKind.Absolute, out Uri? uri):
+ var parameters = new Dictionary(StringComparer.Ordinal);
+
+ if (!string.IsNullOrEmpty(uri.Query))
+ {
+ foreach (var parameter in OpenIddictHelpers.ParseQuery(uri.Query))
+ {
+ parameters[parameter.Key] = parameter.Value.Count switch
+ {
+ 0 => default,
+ 1 => parameter.Value[0],
+ _ => parameter.Value.ToArray()
+ };
+ }
+ }
+
+ // Note: the fragment is always processed after the query string to ensure that
+ // parameters extracted from the fragment are preferred to parameters extracted
+ // from the query string when they are present in both parts.
+
+ if (!string.IsNullOrEmpty(uri.Fragment))
+ {
+ foreach (var parameter in OpenIddictHelpers.ParseFragment(uri.Fragment))
+ {
+ parameters[parameter.Key] = parameter.Value.Count switch
+ {
+ 0 => default,
+ 1 => parameter.Value[0],
+ _ => parameter.Value.ToArray()
+ };
+ }
+ }
+
+ var callback = new OpenIddictClientSystemIntegrationPlatformCallback(uri, parameters)
+ {
+ // Attach the authentication result to the properties.
+ Properties = { [typeof(WebAuthenticationResult).FullName!] = result }
+ };
+
+ await _service.HandlePlatformCallbackAsync(callback, context.CancellationToken);
context.HandleRequest();
return;
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs
index ac0067deb..cef46795c 100644
--- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Session.cs
@@ -57,9 +57,7 @@ public static class Session
*/
ExtractGetOrPostHttpListenerRequest.Descriptor,
ExtractProtocolActivationParameters.Descriptor,
- ExtractASWebAuthenticationCallbackUrlData.Descriptor,
- ExtractCustomTabsIntentData.Descriptor,
- ExtractWebAuthenticationResultData.Descriptor,
+ ExtractPlatformCallbackParameters.Descriptor,
/*
* Post-logout redirection response handling:
@@ -68,9 +66,7 @@ public static class Session
AttachCacheControlHeader.Descriptor,
ProcessEmptyHttpResponse.Descriptor,
ProcessProtocolActivationResponse.Descriptor,
- ProcessASWebAuthenticationSessionResponse.Descriptor,
- ProcessCustomTabsIntentResponse.Descriptor,
- ProcessWebAuthenticationResultResponse.Descriptor
+ ProcessPlatformCallbackResponse.Descriptor
]);
///
@@ -123,7 +119,8 @@ public async ValueTask HandleAsync(ApplyLogoutRequestContext context)
throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0446));
}
- var source = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
+ var source = new TaskCompletionSource(
+ TaskCreationOptions.RunContinuationsAsynchronously);
// OpenIddict represents the complete interactive logout dance as a two-phase process:
// - The sign-out, during which the user is redirected to the authorization server, either
@@ -161,11 +158,11 @@ public async ValueTask HandleAsync(ApplyLogoutRequestContext context)
throw new InvalidOperationException(SR.GetResourceString(SR.ID0448));
}
- NSUrl url;
+ OpenIddictClientSystemIntegrationPlatformCallback callback;
try
{
- url = await source.Task.WaitAsync(context.CancellationToken);
+ callback = await source.Task.WaitAsync(context.CancellationToken);
}
// Since the result of this operation is known by the time the task signaled by ASWebAuthenticationSession
@@ -195,7 +192,7 @@ public async ValueTask HandleAsync(ApplyLogoutRequestContext context)
return;
}
- await _service.HandleASWebAuthenticationCallbackUrlAsync(url, context.CancellationToken);
+ await _service.HandlePlatformCallbackAsync(callback, context.CancellationToken);
context.HandleRequest();
return;
@@ -250,7 +247,43 @@ void HandleCallback(NSUrl? url, NSError? error)
{
if (url is not null)
{
- source.SetResult(url);
+ var parameters = new Dictionary(StringComparer.Ordinal);
+
+ if (!string.IsNullOrEmpty(url.Query))
+ {
+ foreach (var parameter in OpenIddictHelpers.ParseQuery(url.Query))
+ {
+ parameters[parameter.Key] = parameter.Value.Count switch
+ {
+ 0 => default,
+ 1 => parameter.Value[0],
+ _ => parameter.Value.ToArray()
+ };
+ }
+ }
+
+ // Note: the fragment is always processed after the query string to ensure that
+ // parameters extracted from the fragment are preferred to parameters extracted
+ // from the query string when they are present in both parts.
+
+ if (!string.IsNullOrEmpty(url.Fragment))
+ {
+ foreach (var parameter in OpenIddictHelpers.ParseFragment(url.Fragment))
+ {
+ parameters[parameter.Key] = parameter.Value.Count switch
+ {
+ 0 => default,
+ 1 => parameter.Value[0],
+ _ => parameter.Value.ToArray()
+ };
+ }
+ }
+
+ source.SetResult(new OpenIddictClientSystemIntegrationPlatformCallback(url!, parameters)
+ {
+ // Attach the raw URL to the callback properties.
+ Properties = { [typeof(NSUrl).FullName!] = url }
+ });
}
else if (error is not null)
@@ -426,8 +459,47 @@ public async ValueTask HandleAsync(ApplyLogoutRequestContext context)
parameter => new StringValues((string?[]?) parameter.Value))),
callbackUri: new Uri(context.PostLogoutRedirectUri, UriKind.Absolute)))
{
- case { ResponseStatus: WebAuthenticationStatus.Success } result:
- await _service.HandleWebAuthenticationResultAsync(result, context.CancellationToken);
+ case { ResponseStatus: WebAuthenticationStatus.Success } result
+ when Uri.TryCreate(result.ResponseData, UriKind.Absolute, out Uri? uri):
+ var parameters = new Dictionary(StringComparer.Ordinal);
+
+ if (!string.IsNullOrEmpty(uri.Query))
+ {
+ foreach (var parameter in OpenIddictHelpers.ParseQuery(uri.Query))
+ {
+ parameters[parameter.Key] = parameter.Value.Count switch
+ {
+ 0 => default,
+ 1 => parameter.Value[0],
+ _ => parameter.Value.ToArray()
+ };
+ }
+ }
+
+ // Note: the fragment is always processed after the query string to ensure that
+ // parameters extracted from the fragment are preferred to parameters extracted
+ // from the query string when they are present in both parts.
+
+ if (!string.IsNullOrEmpty(uri.Fragment))
+ {
+ foreach (var parameter in OpenIddictHelpers.ParseFragment(uri.Fragment))
+ {
+ parameters[parameter.Key] = parameter.Value.Count switch
+ {
+ 0 => default,
+ 1 => parameter.Value[0],
+ _ => parameter.Value.ToArray()
+ };
+ }
+ }
+
+ var callback = new OpenIddictClientSystemIntegrationPlatformCallback(uri, parameters)
+ {
+ // Attach the authentication result to the properties.
+ Properties = { [typeof(WebAuthenticationResult).FullName!] = result }
+ };
+
+ await _service.HandlePlatformCallbackAsync(callback, context.CancellationToken);
context.HandleRequest();
return;
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs
index aad73fa1b..290b5aede 100644
--- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.cs
@@ -9,7 +9,6 @@
using System.Diagnostics;
using System.Net;
using System.Runtime.CompilerServices;
-using System.Runtime.Versioning;
using System.Security.Claims;
using System.Text;
using Microsoft.Extensions.Hosting;
@@ -24,18 +23,6 @@
using IHostApplicationLifetime = Microsoft.Extensions.Hosting.IApplicationLifetime;
#endif
-#if SUPPORTS_ANDROID
-using NativeUri = Android.Net.Uri;
-#endif
-
-#if SUPPORTS_FOUNDATION
-using Foundation;
-#endif
-
-#if SUPPORTS_WINDOWS_RUNTIME
-using Windows.Security.Authentication.Web;
-#endif
-
namespace OpenIddict.Client.SystemIntegration;
[EditorBrowsable(EditorBrowsableState.Never)]
@@ -47,9 +34,7 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
*/
ResolveRequestUriFromHttpListenerRequest.Descriptor,
ResolveRequestUriFromProtocolActivation.Descriptor,
- ResolveRequestUriFromASWebAuthenticationCallbackUrl.Descriptor,
- ResolveRequestUriFromCustomTabsIntentData.Descriptor,
- ResolveRequestUriFromWebAuthenticationResult.Descriptor,
+ ResolveRequestUriFromPlatformCallback.Descriptor,
InferEndpointTypeFromDynamicAddress.Descriptor,
RejectUnknownHttpRequests.Descriptor,
@@ -215,26 +200,23 @@ public ValueTask HandleAsync(ProcessRequestContext context)
}
///
- /// Contains the logic responsible for resolving the request URI from the AS web authentication session callback URL.
- /// Note: this handler is not used when the OpenID Connect request is not an AS web authentication session callback URL.
+ /// Contains the logic responsible for resolving the request URI from the platform callback details.
+ /// Note: this handler is not used when the OpenID Connect request is not a platform callback.
///
- public sealed class ResolveRequestUriFromASWebAuthenticationCallbackUrl : IOpenIddictClientHandler
+ public sealed class ResolveRequestUriFromPlatformCallback : IOpenIddictClientHandler
{
///
/// Gets the default descriptor definition assigned to this handler.
///
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder()
- .AddFilter()
- .UseSingletonHandler()
+ .AddFilter()
+ .UseSingletonHandler()
.SetOrder(ResolveRequestUriFromProtocolActivation.Descriptor.Order + 1_000)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
///
- [SupportedOSPlatform("ios12.0")]
- [SupportedOSPlatform("maccatalyst13.1")]
- [SupportedOSPlatform("macos10.15")]
public ValueTask HandleAsync(ProcessRequestContext context)
{
if (context is null)
@@ -242,10 +224,9 @@ public ValueTask HandleAsync(ProcessRequestContext context)
throw new ArgumentNullException(nameof(context));
}
-#if SUPPORTS_AUTHENTICATION_SERVICES && SUPPORTS_FOUNDATION
- (context.BaseUri, context.RequestUri) = context.Transaction.GetASWebAuthenticationCallbackUrl() switch
+ (context.BaseUri, context.RequestUri) = context.Transaction.GetPlatformCallback() switch
{
- NSUrl url when Uri.TryCreate(url.AbsoluteString, UriKind.Absolute, out Uri? uri) => (
+ { CallbackUri: Uri uri } => (
BaseUri: new UriBuilder(uri) { Path = null, Query = null, Fragment = null }.Uri,
RequestUri: uri),
@@ -253,52 +234,6 @@ NSUrl url when Uri.TryCreate(url.AbsoluteString, UriKind.Absolute, out Uri? uri)
};
return default;
-#else
- throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0446));
-#endif
- }
- }
-
- ///
- /// Contains the logic responsible for resolving the request URI from the custom tabs intent data.
- /// Note: this handler is not used when the OpenID Connect request is not an custom tabs intent callback.
- ///
- public sealed class ResolveRequestUriFromCustomTabsIntentData : IOpenIddictClientHandler
- {
- ///
- /// Gets the default descriptor definition assigned to this handler.
- ///
- public static OpenIddictClientHandlerDescriptor Descriptor { get; }
- = OpenIddictClientHandlerDescriptor.CreateBuilder()
- .AddFilter()
- .UseSingletonHandler()
- .SetOrder(ResolveRequestUriFromASWebAuthenticationCallbackUrl.Descriptor.Order + 1_000)
- .SetType(OpenIddictClientHandlerType.BuiltIn)
- .Build();
-
- ///
- [SupportedOSPlatform("android21.0")]
- public ValueTask HandleAsync(ProcessRequestContext context)
- {
- if (context is null)
- {
- throw new ArgumentNullException(nameof(context));
- }
-
-#if SUPPORTS_ANDROID
- (context.BaseUri, context.RequestUri) = context.Transaction.GetCustomTabsIntentData() switch
- {
- NativeUri url when Uri.TryCreate(url.ToString(), UriKind.Absolute, out Uri? uri) => (
- BaseUri: new UriBuilder(uri) { Path = null, Query = null, Fragment = null }.Uri,
- RequestUri: uri),
-
- _ => throw new InvalidOperationException(SR.GetResourceString(SR.ID0393))
- };
-
- return default;
-#else
- throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0452));
-#endif
}
}
@@ -306,6 +241,7 @@ NativeUri url when Uri.TryCreate(url.ToString(), UriKind.Absolute, out Uri? uri)
/// Contains the logic responsible for resolving the request URI from the web authentication result.
/// Note: this handler is not used when the OpenID Connect request is not a web authentication result.
///
+ [Obsolete("This event handler is obsolete and will be removed in a future version.")]
public sealed class ResolveRequestUriFromWebAuthenticationResult : IOpenIddictClientHandler
{
///
@@ -315,35 +251,13 @@ public sealed class ResolveRequestUriFromWebAuthenticationResult : IOpenIddictCl
= OpenIddictClientHandlerDescriptor.CreateBuilder()
.AddFilter()
.UseSingletonHandler()
- .SetOrder(ResolveRequestUriFromCustomTabsIntentData.Descriptor.Order + 1_000)
+ .SetOrder(ResolveRequestUriFromPlatformCallback.Descriptor.Order + 1_000)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
///
- [SupportedOSPlatform("windows10.0.17763")]
public ValueTask HandleAsync(ProcessRequestContext context)
- {
- if (context is null)
- {
- throw new ArgumentNullException(nameof(context));
- }
-
-#if SUPPORTS_WINDOWS_RUNTIME
- (context.BaseUri, context.RequestUri) = context.Transaction.GetWebAuthenticationResult() switch
- {
- { ResponseStatus: WebAuthenticationStatus.Success, ResponseData: string data } when
- Uri.TryCreate(data, UriKind.Absolute, out Uri? uri) => (
- BaseUri: new UriBuilder(uri) { Path = null, Query = null, Fragment = null }.Uri,
- RequestUri: uri),
-
- _ => throw new InvalidOperationException(SR.GetResourceString(SR.ID0393))
- };
-
- return default;
-#else
- throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0392));
-#endif
- }
+ => throw new NotSupportedException(SR.GetResourceString(SR.ID0403));
}
///
@@ -671,26 +585,23 @@ public ValueTask HandleAsync(TContext context)
}
///
- /// Contains the logic responsible for extracting OpenID Connect requests from the callback URL of an AS session.
- /// Note: this handler is not used when the OpenID Connect request is not an AS web authentication session callback.
+ /// Contains the logic responsible for extracting OpenID Connect requests from the URI of a platform callback.
+ /// Note: this handler is not used when the OpenID Connect request is not a platform callback.
///
- public sealed class ExtractASWebAuthenticationCallbackUrlData : IOpenIddictClientHandler where TContext : BaseValidatingContext
+ public sealed class ExtractPlatformCallbackParameters : IOpenIddictClientHandler where TContext : BaseValidatingContext
{
///
/// Gets the default descriptor definition assigned to this handler.
///
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder()
- .AddFilter()
- .UseSingletonHandler>()
+ .AddFilter()
+ .UseSingletonHandler>()
.SetOrder(ExtractProtocolActivationParameters.Descriptor.Order + 1_000)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
///
- [SupportedOSPlatform("ios12.0")]
- [SupportedOSPlatform("maccatalyst13.1")]
- [SupportedOSPlatform("macos10.15")]
public ValueTask HandleAsync(TContext context)
{
if (context is null)
@@ -698,105 +609,14 @@ public ValueTask HandleAsync(TContext context)
throw new ArgumentNullException(nameof(context));
}
-#if SUPPORTS_AUTHENTICATION_SERVICES && SUPPORTS_FOUNDATION
- if (context.Transaction.GetASWebAuthenticationCallbackUrl()
- is not NSUrl url || !Uri.TryCreate(url.AbsoluteString, UriKind.Absolute, out Uri? uri))
+ if (context.Transaction.GetPlatformCallback() is not OpenIddictClientSystemIntegrationPlatformCallback callback)
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0393));
}
- var parameters = new Dictionary(StringComparer.Ordinal);
-
- if (!string.IsNullOrEmpty(uri.Query))
- {
- foreach (var parameter in OpenIddictHelpers.ParseQuery(uri.Query))
- {
- parameters[parameter.Key] = parameter.Value;
- }
- }
-
- // Note: the fragment is always processed after the query string to ensure that
- // parameters extracted from the fragment are preferred to parameters extracted
- // from the query string when they are present in both parts.
-
- if (!string.IsNullOrEmpty(uri.Fragment))
- {
- foreach (var parameter in OpenIddictHelpers.ParseFragment(uri.Fragment))
- {
- parameters[parameter.Key] = parameter.Value;
- }
- }
-
- context.Transaction.Request = new OpenIddictRequest(parameters);
+ context.Transaction.Request = new OpenIddictRequest(callback.Parameters);
return default;
-#else
- throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0446));
-#endif
- }
- }
-
- ///
- /// Contains the logic responsible for extracting OpenID Connect requests from the callback URL of a custom tabs intent.
- /// Note: this handler is not used when the OpenID Connect request is not a custom tabs intent result.
- ///
- public sealed class ExtractCustomTabsIntentData : IOpenIddictClientHandler where TContext : BaseValidatingContext
- {
- ///
- /// Gets the default descriptor definition assigned to this handler.
- ///
- public static OpenIddictClientHandlerDescriptor Descriptor { get; }
- = OpenIddictClientHandlerDescriptor.CreateBuilder()
- .AddFilter()
- .UseSingletonHandler>()
- .SetOrder(ExtractProtocolActivationParameters.Descriptor.Order + 1_000)
- .SetType(OpenIddictClientHandlerType.BuiltIn)
- .Build();
-
- ///
- [SupportedOSPlatform("android21.0")]
- public ValueTask HandleAsync(TContext context)
- {
- if (context is null)
- {
- throw new ArgumentNullException(nameof(context));
- }
-
-#if SUPPORTS_ANDROID
- if (context.Transaction.GetCustomTabsIntentData()
- is not NativeUri url || !Uri.TryCreate(url.ToString(), UriKind.Absolute, out Uri? uri))
- {
- throw new InvalidOperationException(SR.GetResourceString(SR.ID0393));
- }
-
- var parameters = new Dictionary(StringComparer.Ordinal);
-
- if (!string.IsNullOrEmpty(uri.Query))
- {
- foreach (var parameter in OpenIddictHelpers.ParseQuery(uri.Query))
- {
- parameters[parameter.Key] = parameter.Value;
- }
- }
-
- // Note: the fragment is always processed after the query string to ensure that
- // parameters extracted from the fragment are preferred to parameters extracted
- // from the query string when they are present in both parts.
-
- if (!string.IsNullOrEmpty(uri.Fragment))
- {
- foreach (var parameter in OpenIddictHelpers.ParseFragment(uri.Fragment))
- {
- parameters[parameter.Key] = parameter.Value;
- }
- }
-
- context.Transaction.Request = new OpenIddictRequest(parameters);
-
- return default;
-#else
- throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0446));
-#endif
}
}
@@ -805,6 +625,7 @@ public ValueTask HandleAsync(TContext context)
/// requests from the response data of a web authentication result.
/// Note: this handler is not used when the OpenID Connect request is not a web authentication result.
///
+ [Obsolete("This event handler is obsolete and will be removed in a future version.")]
public sealed class ExtractWebAuthenticationResultData : IOpenIddictClientHandler where TContext : BaseValidatingContext
{
///
@@ -814,56 +635,13 @@ public sealed class ExtractWebAuthenticationResultData : IOpenIddictCl
= OpenIddictClientHandlerDescriptor.CreateBuilder()
.AddFilter()
.UseSingletonHandler>()
- .SetOrder(ExtractCustomTabsIntentData.Descriptor.Order + 1_000)
+ .SetOrder(ExtractPlatformCallbackParameters.Descriptor.Order + 1_000)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
///
- [SupportedOSPlatform("windows10.0.17763")]
public ValueTask HandleAsync(TContext context)
- {
- if (context is null)
- {
- throw new ArgumentNullException(nameof(context));
- }
-
-#if SUPPORTS_WINDOWS_RUNTIME
- if (context.Transaction.GetWebAuthenticationResult()
- is not { ResponseStatus: WebAuthenticationStatus.Success, ResponseData: string data } ||
- !Uri.TryCreate(data, UriKind.Absolute, out Uri? uri))
- {
- throw new InvalidOperationException(SR.GetResourceString(SR.ID0393));
- }
-
- var parameters = new Dictionary(StringComparer.Ordinal);
-
- if (!string.IsNullOrEmpty(uri.Query))
- {
- foreach (var parameter in OpenIddictHelpers.ParseQuery(uri.Query))
- {
- parameters[parameter.Key] = parameter.Value;
- }
- }
-
- // Note: the fragment is always processed after the query string to ensure that
- // parameters extracted from the fragment are preferred to parameters extracted
- // from the query string when they are present in both parts.
-
- if (!string.IsNullOrEmpty(uri.Fragment))
- {
- foreach (var parameter in OpenIddictHelpers.ParseFragment(uri.Fragment))
- {
- parameters[parameter.Key] = parameter.Value;
- }
- }
-
- context.Transaction.Request = new OpenIddictRequest(parameters);
-
- return default;
-#else
- throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0392));
-#endif
- }
+ => throw new NotSupportedException(SR.GetResourceString(SR.ID0403));
}
///
@@ -2056,7 +1834,7 @@ public async ValueTask HandleAsync(ProcessChallengeContext context)
// the server support response_mode=fragment, use it if the response types contain
// a value that prevents response_mode=query from being used (token/id_token).
({ Count: > 0 } client, { Count: > 0 } server) when
- OpenIddictClientSystemIntegrationHelpers.IsWebAuthenticationBrokerSupported() &&
+ IsWebAuthenticationBrokerSupported() &&
IsAuthenticationMode(OpenIddictClientSystemIntegrationAuthenticationMode.WebAuthenticationBroker) &&
client.Contains(ResponseModes.Fragment) && server.Contains(ResponseModes.Fragment) &&
(types.Contains(ResponseTypes.IdToken) || types.Contains(ResponseTypes.Token))
@@ -2067,7 +1845,7 @@ public async ValueTask HandleAsync(ProcessChallengeContext context)
// assume it is supported and use it if the response types contain a value that
// prevents response_mode=query from being used (token/id_token).
({ Count: > 0 } client, { Count: 0 }) when
- OpenIddictClientSystemIntegrationHelpers.IsWebAuthenticationBrokerSupported() &&
+ IsWebAuthenticationBrokerSupported() &&
IsAuthenticationMode(OpenIddictClientSystemIntegrationAuthenticationMode.WebAuthenticationBroker) &&
client.Contains(ResponseModes.Fragment) &&
(types.Contains(ResponseTypes.IdToken) || types.Contains(ResponseTypes.Token))
@@ -2129,7 +1907,7 @@ await IsEmbeddedWebServerRedirectUriAsync()
// When using the web authentication broker on Windows, if both
// the client and the server support response_mode=fragment, use it.
({ Count: > 0 } client, { Count: > 0 } server) when
- OpenIddictClientSystemIntegrationHelpers.IsWebAuthenticationBrokerSupported() &&
+ IsWebAuthenticationBrokerSupported() &&
IsAuthenticationMode(OpenIddictClientSystemIntegrationAuthenticationMode.WebAuthenticationBroker) &&
client.Contains(ResponseModes.Fragment) && server.Contains(ResponseModes.Fragment)
=> ResponseModes.Fragment,
@@ -2610,43 +2388,7 @@ public sealed class ProcessProtocolActivationResponse : IOpenIddictCli
= OpenIddictClientHandlerDescriptor.CreateBuilder()
.AddFilter()
.UseSingletonHandler>()
- .SetOrder(ProcessWebAuthenticationResultResponse.Descriptor.Order - 1_000)
- .SetType(OpenIddictClientHandlerType.BuiltIn)
- .Build();
-
- ///
- public ValueTask HandleAsync(TContext context)
- {
- if (context is null)
- {
- throw new ArgumentNullException(nameof(context));
- }
-
- // For both protocol activations (initial or redirected) and web-view-like results,
- // no proper response can be generated and eventually displayed to the user. In this
- // case, simply stop processing the response and mark the request as fully handled.
- //
- // Note: this logic applies to both successful and errored responses.
-
- context.HandleRequest();
- return default;
- }
- }
-
- ///
- /// Contains the logic responsible for marking OpenID Connect responses returned via a custom tabs intent web as processed.
- ///
- public sealed class ProcessCustomTabsIntentResponse : IOpenIddictClientHandler
- where TContext : BaseRequestContext
- {
- ///
- /// Gets the default descriptor definition assigned to this handler.
- ///
- public static OpenIddictClientHandlerDescriptor Descriptor { get; }
- = OpenIddictClientHandlerDescriptor.CreateBuilder()
- .AddFilter()
- .UseSingletonHandler>()
- .SetOrder(int.MaxValue)
+ .SetOrder(ProcessPlatformCallbackResponse.Descriptor.Order - 1_000)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
@@ -2670,10 +2412,9 @@ public ValueTask HandleAsync(TContext context)
}
///
- /// Contains the logic responsible for marking OpenID Connect responses
- /// returned via AS web authentication callback URLs as processed.
+ /// Contains the logic responsible for marking OpenID Connect responses returned via a platform callback.
///
- public sealed class ProcessASWebAuthenticationSessionResponse : IOpenIddictClientHandler
+ public sealed class ProcessPlatformCallbackResponse : IOpenIddictClientHandler
where TContext : BaseRequestContext
{
///
@@ -2681,8 +2422,8 @@ public sealed class ProcessASWebAuthenticationSessionResponse : IOpenI
///
public static OpenIddictClientHandlerDescriptor Descriptor { get; }
= OpenIddictClientHandlerDescriptor.CreateBuilder()
- .AddFilter()
- .UseSingletonHandler>()
+ .AddFilter()
+ .UseSingletonHandler>()
.SetOrder(int.MaxValue)
.SetType(OpenIddictClientHandlerType.BuiltIn)
.Build();
@@ -2710,6 +2451,7 @@ public ValueTask HandleAsync(TContext context)
/// Contains the logic responsible for marking OpenID Connect
/// responses returned via web authentication results as processed.
///
+ [Obsolete("This handler is obsolete and will be removed in a future version.")]
public sealed class ProcessWebAuthenticationResultResponse : IOpenIddictClientHandler
where TContext : BaseRequestContext
{
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHelpers.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHelpers.cs
index f29678dd8..ccb11fe3a 100644
--- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHelpers.cs
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHelpers.cs
@@ -44,6 +44,14 @@ namespace OpenIddict.Client.SystemIntegration;
///
public static class OpenIddictClientSystemIntegrationHelpers
{
+ ///
+ /// Gets the associated with the current context.
+ ///
+ /// The transaction instance.
+ /// The instance or if it couldn't be found.
+ public static OpenIddictClientSystemIntegrationPlatformCallback? GetPlatformCallback(this OpenIddictClientTransaction transaction)
+ => transaction.GetProperty(typeof(OpenIddictClientSystemIntegrationPlatformCallback).FullName!);
+
///
/// Gets the associated with the current context.
///
@@ -60,39 +68,17 @@ public static class OpenIddictClientSystemIntegrationHelpers
public static HttpListenerContext? GetHttpListenerContext(this OpenIddictClientTransaction transaction)
=> transaction.GetProperty(typeof(HttpListenerContext).FullName!);
-#if SUPPORTS_AUTHENTICATION_SERVICES && SUPPORTS_FOUNDATION
- ///
- /// Gets the AS web authentication callback URL associated with the current context.
- ///
- /// The transaction instance.
- /// The instance or if it couldn't be found.
- [SupportedOSPlatform("ios12.0")]
- [SupportedOSPlatform("maccatalyst13.1")]
- [SupportedOSPlatform("macos10.15")]
- public static NSUrl? GetASWebAuthenticationCallbackUrl(this OpenIddictClientTransaction transaction)
- => transaction.GetProperty(typeof(NSUrl).FullName!);
-#endif
-
-#if SUPPORTS_ANDROID && SUPPORTS_ANDROIDX_BROWSER
- ///
- /// Gets the custom tabs intent data associated with the current context.
- ///
- /// The transaction instance.
- /// The instance or if it couldn't be found.
- [SupportedOSPlatform("android21.0")]
- public static NativeUri? GetCustomTabsIntentData(this OpenIddictClientTransaction transaction)
- => transaction.GetProperty(typeof(NativeUri).FullName!);
-#endif
-
#if SUPPORTS_WINDOWS_RUNTIME
///
/// Gets the associated with the current context.
///
/// The transaction instance.
/// The instance or if it couldn't be found.
- [SupportedOSPlatform("windows10.0.17763")]
+ [Obsolete("This extension is obsolete and will be removed in a future version."), SupportedOSPlatform("windows10.0.17763")]
public static WebAuthenticationResult? GetWebAuthenticationResult(this OpenIddictClientTransaction transaction)
- => transaction.GetProperty(typeof(WebAuthenticationResult).FullName!);
+ => transaction.GetPlatformCallback() is OpenIddictClientSystemIntegrationPlatformCallback callback &&
+ callback.Properties.TryGetValue(typeof(WebAuthenticationResult).FullName!, out object? property) &&
+ property is WebAuthenticationResult result ? result : null;
#endif
///
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationPlatformCallback.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationPlatformCallback.cs
new file mode 100644
index 000000000..66efa756d
--- /dev/null
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationPlatformCallback.cs
@@ -0,0 +1,62 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
+ * See https://github.com/openiddict/openiddict-core for more information concerning
+ * the license and the contributors participating to this project.
+ */
+
+using System.Collections.Immutable;
+using System.ComponentModel;
+using OpenIddict.Extensions;
+
+namespace OpenIddict.Client.SystemIntegration;
+
+///
+/// Represents a generic platform callback.
+///
+[EditorBrowsable(EditorBrowsableState.Advanced)]
+public sealed class OpenIddictClientSystemIntegrationPlatformCallback
+{
+ ///
+ /// Creates a new instance of the class.
+ ///
+ /// The callback URI.
+ /// The callback parameters.
+ /// is .
+ /// is .
+ public OpenIddictClientSystemIntegrationPlatformCallback(
+ Uri uri, IReadOnlyDictionary parameters)
+ {
+ if (uri is null)
+ {
+ throw new ArgumentNullException(nameof(uri));
+ }
+
+ if (!uri.IsAbsoluteUri || OpenIddictHelpers.IsImplicitFileUri(uri))
+ {
+ throw new ArgumentException(SR.GetResourceString(SR.ID0144), nameof(uri));
+ }
+
+ if (parameters is null)
+ {
+ throw new ArgumentNullException(nameof(parameters));
+ }
+
+ CallbackUri = uri;
+ Parameters = parameters.ToImmutableDictionary();
+ }
+
+ ///
+ /// Gets the callback URI.
+ ///
+ public Uri CallbackUri { get; }
+
+ ///
+ /// Gets the parameters attached to this instance.
+ ///
+ public ImmutableDictionary Parameters { get; }
+
+ ///
+ /// Gets the additional properties attached to this instance.
+ ///
+ public Dictionary Properties { get; } = new(StringComparer.Ordinal);
+}
diff --git a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationService.cs b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationService.cs
index 729cf17cc..606c5b4c7 100644
--- a/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationService.cs
+++ b/src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationService.cs
@@ -7,22 +7,13 @@
using System.ComponentModel;
using System.IO.Pipes;
using System.Net;
-using System.Runtime.Versioning;
using System.Security.Principal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
+using OpenIddict.Extensions;
#if SUPPORTS_ANDROID
using Android.Content;
-using NativeUri = Android.Net.Uri;
-#endif
-
-#if SUPPORTS_FOUNDATION
-using Foundation;
-#endif
-
-#if SUPPORTS_WINDOWS_RUNTIME
-using Windows.Security.Authentication.Web;
#endif
namespace OpenIddict.Client.SystemIntegration;
@@ -51,18 +42,6 @@ public OpenIddictClientSystemIntegrationService(
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
}
- ///
- /// Handles the specified protocol activation.
- ///
- /// The protocol activation details.
- /// The that can be used to abort the operation.
- /// A that can be used to monitor the asynchronous operation.
- /// is .
- [EditorBrowsable(EditorBrowsableState.Advanced)]
- public Task HandleProtocolActivationAsync(
- OpenIddictClientSystemIntegrationActivation activation, CancellationToken cancellationToken = default)
- => HandleRequestAsync(activation ?? throw new ArgumentNullException(nameof(activation)), cancellationToken);
-
#if SUPPORTS_ANDROID && SUPPORTS_ANDROIDX_BROWSER
///
/// Handles the specified intent.
@@ -73,46 +52,93 @@ public Task HandleProtocolActivationAsync(
/// is .
[EditorBrowsable(EditorBrowsableState.Advanced)]
public Task HandleCustomTabsIntentAsync(Intent intent, CancellationToken cancellationToken = default)
- => HandleRequestAsync(intent?.Data ?? throw new ArgumentNullException(nameof(intent)), cancellationToken);
+ {
+ if (intent is null)
+ {
+ throw new ArgumentNullException(nameof(intent));
+ }
+
+ if (intent.Data is null)
+ {
+ throw new ArgumentException(SR.GetResourceString(SR.ID0453), nameof(intent));
+ }
+
+ var parameters = new Dictionary(StringComparer.Ordinal);
+
+ if (!string.IsNullOrEmpty(intent.Data.Query))
+ {
+ foreach (var parameter in OpenIddictHelpers.ParseQuery(intent.Data.Query))
+ {
+ parameters[parameter.Key] = parameter.Value.Count switch
+ {
+ 0 => default,
+ 1 => parameter.Value[0],
+ _ => parameter.Value.ToArray()
+ };
+ }
+ }
+
+ // Note: the fragment is always processed after the query string to ensure that
+ // parameters extracted from the fragment are preferred to parameters extracted
+ // from the query string when they are present in both parts.
+
+ if (!string.IsNullOrEmpty(intent.Data.Fragment))
+ {
+ foreach (var parameter in OpenIddictHelpers.ParseFragment(intent.Data.Fragment))
+ {
+ parameters[parameter.Key] = parameter.Value.Count switch
+ {
+ 0 => default,
+ 1 => parameter.Value[0],
+ _ => parameter.Value.ToArray()
+ };
+ }
+ }
+
+ var uri = new Uri(intent.Data.ToString()!, UriKind.Absolute);
+ var callback = new OpenIddictClientSystemIntegrationPlatformCallback(uri, parameters)
+ {
+ // Attach the intent to the properties.
+ Properties = { [typeof(Intent).FullName!] = intent }
+ };
+
+ return HandlePlatformCallbackAsync(callback, cancellationToken);
+ }
#endif
///
- /// Handles the specified HTTP request.
+ /// Handles the specified platform callback.
///
- /// The HTTP request received by the embedded web server.
+ /// The platform callback details.
/// The that can be used to abort the operation.
/// A that can be used to monitor the asynchronous operation.
- /// is .
- internal Task HandleHttpRequestAsync(HttpListenerContext request, CancellationToken cancellationToken = default)
- => HandleRequestAsync(request ?? throw new ArgumentNullException(nameof(request)), cancellationToken);
+ /// is .
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public Task HandlePlatformCallbackAsync(
+ OpenIddictClientSystemIntegrationPlatformCallback callback, CancellationToken cancellationToken = default)
+ => HandleRequestAsync(callback ?? throw new ArgumentNullException(nameof(callback)), cancellationToken);
-#if SUPPORTS_AUTHENTICATION_SERVICES && SUPPORTS_FOUNDATION
///
- /// Handles the specified AS web authentication session callback URL.
+ /// Handles the specified protocol activation.
///
- /// The AS web authentication session callback URL.
+ /// The protocol activation details.
/// The that can be used to abort the operation.
/// A that can be used to monitor the asynchronous operation.
- /// is .
- [SupportedOSPlatform("ios12.0")]
- [SupportedOSPlatform("maccatalyst13.1")]
- [SupportedOSPlatform("macos10.15")]
- internal Task HandleASWebAuthenticationCallbackUrlAsync(NSUrl url, CancellationToken cancellationToken = default)
- => HandleRequestAsync(url, cancellationToken);
-#endif
+ /// is .
+ [EditorBrowsable(EditorBrowsableState.Advanced)]
+ public Task HandleProtocolActivationAsync(
+ OpenIddictClientSystemIntegrationActivation activation, CancellationToken cancellationToken = default)
+ => HandleRequestAsync(activation ?? throw new ArgumentNullException(nameof(activation)), cancellationToken);
-#if SUPPORTS_WINDOWS_RUNTIME
///
- /// Handles the specified web authentication result.
+ /// Handles the specified HTTP request.
///
- /// The web authentication result.
+ /// The HTTP request received by the embedded web server.
/// The that can be used to abort the operation.
/// A that can be used to monitor the asynchronous operation.
- /// is .
- [SupportedOSPlatform("windows10.0.17763")]
- internal Task HandleWebAuthenticationResultAsync(WebAuthenticationResult result, CancellationToken cancellationToken = default)
- => HandleRequestAsync(result ?? throw new ArgumentNullException(nameof(result)), cancellationToken);
-#endif
+ /// is .
+ internal Task HandleHttpRequestAsync(HttpListenerContext request, CancellationToken cancellationToken = default)
+ => HandleRequestAsync(request ?? throw new ArgumentNullException(nameof(request)), cancellationToken);
///
/// Handles the request using the specified property.
diff --git a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Discovery.cs b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Discovery.cs
index db2f4afa2..58d5c6bd3 100644
--- a/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Discovery.cs
+++ b/src/OpenIddict.Client.WebIntegration/OpenIddictClientWebIntegrationHandlers.Discovery.cs
@@ -263,7 +263,7 @@ public ValueTask HandleAsync(HandleConfigurationResponseContext context)
/// Contains the logic responsible for amending the client authentication methods
/// supported by the device authorization endpoint for the providers that require it.
///
- [Obsolete("This class is obsolete and will be removed in a future version.", error: true)]
+ [Obsolete("This event handler is obsolete and will be removed in a future version.", error: true)]
public sealed class AmendDeviceAuthorizationEndpointClientAuthenticationMethods : IOpenIddictClientHandler
{
///
@@ -285,7 +285,7 @@ public ValueTask HandleAsync(HandleConfigurationResponseContext context)
/// Contains the logic responsible for amending the client authentication
/// methods supported by the token endpoint for the providers that require it.
///
- [Obsolete("This class is obsolete and will be removed in a future version.", error: true)]
+ [Obsolete("This event handler is obsolete and will be removed in a future version.", error: true)]
public sealed class AmendTokenEndpointClientAuthenticationMethods : IOpenIddictClientHandler
{
///
diff --git a/src/OpenIddict.Server/OpenIddictServerHandlers.Protection.cs b/src/OpenIddict.Server/OpenIddictServerHandlers.Protection.cs
index 07bd994ce..3f91fbd18 100644
--- a/src/OpenIddict.Server/OpenIddictServerHandlers.Protection.cs
+++ b/src/OpenIddict.Server/OpenIddictServerHandlers.Protection.cs
@@ -1562,7 +1562,7 @@ public async ValueTask HandleAsync(GenerateTokenContext context)
/// Contains the logic responsible for beautifying user-typed tokens.
/// Note: this handler is not used when the degraded mode is enabled.
///
- [Obsolete("This class is obsolete and will be removed in a future version.", error: true)]
+ [Obsolete("This event handler is obsolete and will be removed in a future version.", error: true)]
public sealed class BeautifyToken : IOpenIddictServerHandler
{
///