Browse Source

Throw an exception if no CoreWindow is attached to the thread starting the challenge demand

pull/1780/head
Kévin Chalet 3 years ago
parent
commit
8777dc9922
  1. 2
      src/OpenIddict.Abstractions/OpenIddictResources.resx
  2. 2
      src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationActivationHandler.cs
  3. 8
      src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationBuilder.cs
  4. 9
      src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationConfiguration.cs
  5. 4
      src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlerFilters.cs
  6. 17
      src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Authentication.cs
  7. 80
      src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHelpers.cs

2
src/OpenIddict.Abstractions/OpenIddictResources.resx

@ -1475,7 +1475,7 @@ To apply post-logout redirection responses, create a class implementing 'IOpenId
<value>An error occurred while instantiating the embedded web server, which may indicate a permission issue.</value> <value>An error occurred while instantiating the embedded web server, which may indicate a permission issue.</value>
</data> </data>
<data name="ID0392" xml:space="preserve"> <data name="ID0392" xml:space="preserve">
<value>The web authentication broker is not supported on this platform.</value> <value>The web authentication broker is only supported on UWP and requires running Windows 10 version 1709 (Fall Creators) or higher.</value>
</data> </data>
<data name="ID0393" xml:space="preserve"> <data name="ID0393" xml:space="preserve">
<value>The web authentication result cannot be resolved or contains invalid data.</value> <value>The web authentication result cannot be resolved or contains invalid data.</value>

2
src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationActivationHandler.cs

@ -72,7 +72,7 @@ public sealed class OpenIddictClientSystemIntegrationActivationHandler : IHosted
{ {
#if SUPPORTS_WINDOWS_RUNTIME #if SUPPORTS_WINDOWS_RUNTIME
// On platforms that support WinRT, always favor the AppInstance.GetActivatedEventArgs() API. // On platforms that support WinRT, always favor the AppInstance.GetActivatedEventArgs() API.
if (OpenIddictClientSystemIntegrationHelpers.IsWindowsRuntimeSupported() && if (OpenIddictClientSystemIntegrationHelpers.IsAppInstanceActivationSupported() &&
OpenIddictClientSystemIntegrationHelpers.GetProtocolActivationUriWithWindowsRuntime() is Uri uri) OpenIddictClientSystemIntegrationHelpers.GetProtocolActivationUriWithWindowsRuntime() is Uri uri)
{ {
return new OpenIddictClientSystemIntegrationActivation(uri); return new OpenIddictClientSystemIntegrationActivation(uri);

8
src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationBuilder.cs

@ -7,7 +7,6 @@
using System.ComponentModel; using System.ComponentModel;
using System.IO.Pipes; using System.IO.Pipes;
using System.Net; using System.Net;
using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
using OpenIddict.Client.SystemIntegration; using OpenIddict.Client.SystemIntegration;
@ -61,12 +60,7 @@ public sealed class OpenIddictClientSystemIntegrationBuilder
[SupportedOSPlatform("windows10.0.17763")] [SupportedOSPlatform("windows10.0.17763")]
public OpenIddictClientSystemIntegrationBuilder UseWebAuthenticationBroker() public OpenIddictClientSystemIntegrationBuilder UseWebAuthenticationBroker()
{ {
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) if (!OpenIddictClientSystemIntegrationHelpers.IsWebAuthenticationBrokerSupported())
{
throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0392));
}
if (!OpenIddictClientSystemIntegrationHelpers.IsWindowsRuntimeSupported())
{ {
throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0392)); throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0392));
} }

9
src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationConfiguration.cs

@ -80,6 +80,15 @@ public sealed class OpenIddictClientSystemIntegrationConfiguration : IConfigureO
throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0389)); throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0389));
} }
#pragma warning disable CA1416
// If explicitly set, ensure the specified authentication mode is supported.
if (options.AuthenticationMode is OpenIddictClientSystemIntegrationAuthenticationMode.WebAuthenticationBroker &&
!OpenIddictClientSystemIntegrationHelpers.IsWebAuthenticationBrokerSupported())
{
throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0392));
}
#pragma warning restore CA1416
// Note: the OpenIddict client system integration is currently only supported on Windows // Note: the OpenIddict client system integration is currently only supported on Windows
// and Linux. As such, using the system browser as the default authentication method in // and Linux. As such, using the system browser as the default authentication method in
// conjunction with the embedded web server and activation handling should be always supported. // conjunction with the embedded web server and activation handling should be always supported.

4
src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlerFilters.cs

@ -135,7 +135,7 @@ public static class OpenIddictClientSystemIntegrationHandlerFilters
} }
#if SUPPORTS_WINDOWS_RUNTIME #if SUPPORTS_WINDOWS_RUNTIME
if (OpenIddictClientSystemIntegrationHelpers.IsWindowsRuntimeSupported()) if (OpenIddictClientSystemIntegrationHelpers.IsWebAuthenticationBrokerSupported())
{ {
if (!context.Transaction.Properties.TryGetValue( if (!context.Transaction.Properties.TryGetValue(
typeof(OpenIddictClientSystemIntegrationAuthenticationMode).FullName!, out var result) || typeof(OpenIddictClientSystemIntegrationAuthenticationMode).FullName!, out var result) ||
@ -166,7 +166,7 @@ public static class OpenIddictClientSystemIntegrationHandlerFilters
} }
#if SUPPORTS_WINDOWS_RUNTIME #if SUPPORTS_WINDOWS_RUNTIME
if (OpenIddictClientSystemIntegrationHelpers.IsWindowsRuntimeSupported()) if (OpenIddictClientSystemIntegrationHelpers.IsWebAuthenticationBrokerSupported())
{ {
return new(ContainsWebAuthenticationResult(context.Transaction)); return new(ContainsWebAuthenticationResult(context.Transaction));
} }

17
src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHandlers.Authentication.cs

@ -14,6 +14,7 @@ using OpenIddict.Extensions;
#if SUPPORTS_WINDOWS_RUNTIME #if SUPPORTS_WINDOWS_RUNTIME
using Windows.Security.Authentication.Web; using Windows.Security.Authentication.Web;
using Windows.UI.Core;
#endif #endif
namespace OpenIddict.Client.SystemIntegration; namespace OpenIddict.Client.SystemIntegration;
@ -87,6 +88,20 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
return; return;
} }
// Note: WebAuthenticationBroker internally requires a pointer to the CoreWindow object associated
// to the thread from which the challenge operation is started. Unfortunately, CoreWindow - and by
// extension WebAuthenticationBroker - are only supported on UWP and cannot be used in Win32 apps.
//
// To ensure a meaningful exception is returned when the web authentication broker is used with an
// incompatible application model (e.g WinUI 3.0), the presence of a CoreWindow is verified here.
//
// See https://github.com/microsoft/WindowsAppSDK/issues/398 for more information.
if (!OpenIddictClientSystemIntegrationHelpers.IsWebAuthenticationBrokerSupported() ||
CoreWindow.GetForCurrentThread() is null)
{
throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0392));
}
// OpenIddict represents the complete interactive authentication dance as a two-phase process: // 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 // - The challenge, during which the user is redirected to the authorization server, either
// by launching the system browser or, as in this case, using a web-view-like approach. // by launching the system browser or, as in this case, using a web-view-like approach.
@ -214,7 +229,7 @@ public static partial class OpenIddictClientSystemIntegrationHandlers
// Runtime APIs and favor the Launcher.LaunchUriAsync() API when it's offered by the platform. // Runtime APIs and favor the Launcher.LaunchUriAsync() API when it's offered by the platform.
#if SUPPORTS_WINDOWS_RUNTIME #if SUPPORTS_WINDOWS_RUNTIME
if (OpenIddictClientSystemIntegrationHelpers.IsWindowsRuntimeSupported() && await if (OpenIddictClientSystemIntegrationHelpers.IsUriLauncherSupported() && await
OpenIddictClientSystemIntegrationHelpers.TryLaunchBrowserWithWindowsRuntimeAsync(uri)) OpenIddictClientSystemIntegrationHelpers.TryLaunchBrowserWithWindowsRuntimeAsync(uri))
{ {
context.HandleRequest(); context.HandleRequest();

80
src/OpenIddict.Client.SystemIntegration/OpenIddictClientSystemIntegrationHelpers.cs

@ -24,7 +24,7 @@ using Windows.System;
namespace OpenIddict.Client.SystemIntegration; namespace OpenIddict.Client.SystemIntegration;
/// <summary> /// <summary>
/// Exposes companion extensions for the OpenIddict/Windows integration. /// Exposes companion extensions for the OpenIddict/system integration.
/// </summary> /// </summary>
public static class OpenIddictClientSystemIntegrationHelpers public static class OpenIddictClientSystemIntegrationHelpers
{ {
@ -101,6 +101,72 @@ public static class OpenIddictClientSystemIntegrationHelpers
// oldest supported version in the package, it is also used for the runtime check. // oldest supported version in the package, it is also used for the runtime check.
internal static bool IsWindowsRuntimeSupported() => IsWindowsVersionAtLeast(10, 0, 17763); internal static bool IsWindowsRuntimeSupported() => IsWindowsVersionAtLeast(10, 0, 17763);
/// <summary>
/// Determines whether WinRT app instance activation is supported on this platform.
/// </summary>
/// <returns>
/// <see langword="true"/> if WinRT app instance activation is supported, <see langword="false"/> otherwise.
/// </returns>
[SupportedOSPlatformGuard("windows10.0.17763")]
internal static bool IsAppInstanceActivationSupported()
{
#if SUPPORTS_WINDOWS_RUNTIME
return IsWindowsRuntimeSupported() && IsApiPresent();
[MethodImpl(MethodImplOptions.NoInlining)]
static bool IsApiPresent() => ApiInformation.IsMethodPresent(
typeName : typeof(AppInstance).FullName,
methodName : nameof(AppInstance.GetActivatedEventArgs),
inputParameterCount: 0);
#else
return false;
#endif
}
/// <summary>
/// Determines whether the WinRT URI launcher is supported on this platform.
/// </summary>
/// <returns>
/// <see langword="true"/> if the WinRT URI launcher is supported, <see langword="false"/> otherwise.
/// </returns>
[SupportedOSPlatformGuard("windows10.0.17763")]
internal static bool IsUriLauncherSupported()
{
#if SUPPORTS_WINDOWS_RUNTIME
return IsWindowsRuntimeSupported() && IsApiPresent();
[MethodImpl(MethodImplOptions.NoInlining)]
static bool IsApiPresent() => ApiInformation.IsMethodPresent(
typeName : typeof(Launcher).FullName,
methodName : nameof(Launcher.LaunchUriAsync),
inputParameterCount: 1);
#else
return false;
#endif
}
/// <summary>
/// Determines whether the WinRT web authentication broker is supported on this platform.
/// </summary>
/// <returns>
/// <see langword="true"/> if the WinRT web authentication broker is supported, <see langword="false"/> otherwise.
/// </returns>
[SupportedOSPlatformGuard("windows10.0.17763")]
internal static bool IsWebAuthenticationBrokerSupported()
{
#if SUPPORTS_WINDOWS_RUNTIME
return IsWindowsRuntimeSupported() && IsApiPresent();
[MethodImpl(MethodImplOptions.NoInlining)]
static bool IsApiPresent() => ApiInformation.IsMethodPresent(
typeName : typeof(WebAuthenticationBroker).FullName,
methodName : nameof(WebAuthenticationBroker.AuthenticateAsync),
inputParameterCount: 3);
#else
return false;
#endif
}
/// <summary> /// <summary>
/// Determines whether the specified identity contains an AppContainer /// Determines whether the specified identity contains an AppContainer
/// token, indicating it's running in an AppContainer sandbox. /// token, indicating it's running in an AppContainer sandbox.
@ -153,12 +219,6 @@ public static class OpenIddictClientSystemIntegrationHelpers
[MethodImpl(MethodImplOptions.NoInlining), SupportedOSPlatform("windows10.0.17763")] [MethodImpl(MethodImplOptions.NoInlining), SupportedOSPlatform("windows10.0.17763")]
internal static Uri? GetProtocolActivationUriWithWindowsRuntime() internal static Uri? GetProtocolActivationUriWithWindowsRuntime()
{ {
if (!ApiInformation.IsMethodPresent(typeof(AppInstance).FullName,
nameof(AppInstance.GetActivatedEventArgs), inputParameterCount: 0))
{
return null;
}
try try
{ {
return AppInstance.GetActivatedEventArgs() is return AppInstance.GetActivatedEventArgs() is
@ -185,12 +245,6 @@ public static class OpenIddictClientSystemIntegrationHelpers
// is implemented via a .NET Standard 2.0 TFM (which requires Windows 10 1809), it is assumed // is implemented via a .NET Standard 2.0 TFM (which requires Windows 10 1809), it is assumed
// at this point that Launcher.LaunchUriAsync() can be used in both types of applications. // at this point that Launcher.LaunchUriAsync() can be used in both types of applications.
if (!ApiInformation.IsMethodPresent(typeof(Launcher).FullName,
nameof(Launcher.LaunchUriAsync), inputParameterCount: 1))
{
return false;
}
try try
{ {
return await Launcher.LaunchUriAsync(uri); return await Launcher.LaunchUriAsync(uri);

Loading…
Cancel
Save