/* * 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.Runtime.InteropServices; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using OpenIddict.Client; using OpenIddict.Client.SystemIntegration; namespace Microsoft.Extensions.DependencyInjection; /// /// Exposes extensions allowing to register the OpenIddict client services. /// public static class OpenIddictClientSystemIntegrationExtensions { /// /// Registers the OpenIddict client system integration services in the DI container. /// /// The services builder used by OpenIddict to register new services. /// This extension can be safely called multiple times. /// The . public static OpenIddictClientSystemIntegrationBuilder UseSystemIntegration(this OpenIddictClientBuilder builder) { if (builder is null) { throw new ArgumentNullException(nameof(builder)); } // Ensure the operating system is supported. if (!RuntimeInformation.IsOSPlatform(OSPlatform.Create("android")) && !RuntimeInformation.IsOSPlatform(OSPlatform.Create("ios")) && !RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && !RuntimeInformation.IsOSPlatform(OSPlatform.Create("maccatalyst")) && !RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0389)); } #if !SUPPORTS_ANDROID // When running on Android, iOS, Mac Catalyst or macOS, ensure the version compiled for // these platforms is used to prevent the generic/non-OS specific TFM from being used. if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("android"))) { throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0449)); } #endif #if !SUPPORTS_APPKIT if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { 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)) || (OperatingSystem.IsIOS() && !OperatingSystem.IsIOSVersionAtLeast(12)) || (OperatingSystem.IsMacCatalyst() && !OperatingSystem.IsMacCatalystVersionAtLeast(13, 1)) || (OperatingSystem.IsMacOS() && !OperatingSystem.IsMacOSVersionAtLeast(10, 15)) || (OperatingSystem.IsWindows() && !OperatingSystem.IsWindowsVersionAtLeast(7))) { throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0389)); } #else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && !IsWindowsVersionAtLeast(7)) { throw new PlatformNotSupportedException(SR.GetResourceString(SR.ID0389)); } #endif // Note: the OpenIddict activation handler service is deliberately registered as early as possible to // ensure protocol activations can be handled before another service can stop the initialization of the // application (e.g Dapplo.Microsoft.Extensions.Hosting.AppServices relies on an IHostedService to implement // single instantiation, which would prevent the OpenIddict service from handling the protocol activation // if the OpenIddict activation handler service was not registered before the Dapplo IHostedService). if (!builder.Services.Any(static descriptor => descriptor.ServiceType == typeof(IHostedService) && descriptor.ImplementationType == typeof(OpenIddictClientSystemIntegrationActivationHandler))) { builder.Services.Insert(0, ServiceDescriptor.Singleton()); } // Register the services responsible for coordinating and managing authentication operations. builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(); builder.Services.TryAddSingleton(static provider => provider.GetServices() .OfType() .Single()); // 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(); #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. builder.Services.TryAdd(OpenIddictClientSystemIntegrationHandlers.DefaultHandlers.Select(descriptor => descriptor.ServiceDescriptor)); // Register the option initializer and the background service used by the OpenIddict client system integration services. // Note: TryAddEnumerable() is used here to ensure the initializers and the background service are only registered once. builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton()); builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton()); builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton< IConfigureOptions, OpenIddictClientSystemIntegrationConfiguration>()); builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton< IPostConfigureOptions, OpenIddictClientSystemIntegrationConfiguration>()); builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton< IPostConfigureOptions, OpenIddictClientSystemIntegrationConfiguration>()); return new OpenIddictClientSystemIntegrationBuilder(builder.Services); } /// /// Registers the OpenIddict client system integration services in the DI container. /// /// The services builder used by OpenIddict to register new services. /// The configuration delegate used to configure the client services. /// This extension can be safely called multiple times. /// The . public static OpenIddictClientBuilder UseSystemIntegration( this OpenIddictClientBuilder builder, Action configuration) { if (builder is null) { throw new ArgumentNullException(nameof(builder)); } if (configuration is null) { throw new ArgumentNullException(nameof(configuration)); } configuration(builder.UseSystemIntegration()); return builder; } }