private IConfidentialClientApplication GetOrCreateApplication()
        {
            if (_application == null)
            {
                lock (_applicationSyncObj)
                {
                    if (_application == null)
                    {
                        var options = new ConfidentialClientApplicationOptions()
                        {
                            ClientId     = AppServicesAuthenticationInformation.ClientId,
                            ClientSecret = AppServicesAuthenticationInformation.ClientSecret,
                            Instance     = AppServicesAuthenticationInformation.Issuer,
                        };
                        _application = ConfidentialClientApplicationBuilder.CreateWithApplicationOptions(options)
                                       .WithHttpClientFactory(_httpClientFactory)
                                       .Build();
                        _tokenCacheProvider.Initialize(_application.AppTokenCache);
                        _tokenCacheProvider.Initialize(_application.UserTokenCache);
                    }
                }
            }

            return(_application);
        }
        /// <summary>
        /// Use a token cache and choose the serialization part by adding it to
        /// the services collection and configuring its options.
        /// </summary>
        /// <returns>The confidential client application.</returns>
        /// <param name="confidentialClientApp">Confidential client application.</param>
        /// <param name="initializeCaches">Action that you'll use to add a cache serialization
        /// to the service collection passed as an argument.</param>
        /// <returns>The application for chaining.</returns>
        /// <example>
        ///
        /// The following code adds a distributed in-memory token cache.
        ///
        /// <code>
        ///  app.AddTokenCaches(services =>
        ///  {
        ///      // In memory distributed token cache
        ///      // In net472, requires to reference Microsoft.Extensions.Caching.Memory
        ///      services.AddDistributedTokenCache();
        ///      services.AddDistributedMemoryCache();
        ///  });
        /// </code>
        ///
        /// The following code adds a token cache based on REDIS and initializes
        /// its configuration.
        ///
        /// <code>
        ///  app.AddTokenCaches(services =>
        ///  {
        ///       services.AddDistributedTokenCache();
        ///       // Redis token cache
        ///       // Requires to reference Microsoft.Extensions.Caching.StackExchangeRedis
        ///       services.AddStackExchangeRedisCache(options =>
        ///       {
        ///           options.Configuration = "localhost";
        ///           options.InstanceName = "Redis";
        ///       });
        ///  });
        /// </code>
        /// If using distributed token caches, use AddDistributedTokenCache.
        /// </example>
        /// <remarks>Don't use this method in ASP.NET Core. Just add use the ConfigureServices method
        /// instead.</remarks>
        internal static IConfidentialClientApplication AddTokenCaches(
            this IConfidentialClientApplication confidentialClientApp,
            Action <IServiceCollection> initializeCaches)
        {
            _ = confidentialClientApp ?? throw new ArgumentNullException(nameof(confidentialClientApp));
            _ = initializeCaches ?? throw new ArgumentNullException(nameof(initializeCaches));

            // try to reuse existing XYZ cache if AddXYZCache was called before, to simulate ASP.NET Core
            var serviceProvider = s_serviceProviderFromAction.GetOrAdd(initializeCaches.Method, (m) =>
            {
                lock (s_serviceProviderFromAction)
                {
                    ServiceCollection services = new ServiceCollection();
                    initializeCaches(services);
                    services.AddLogging();

                    return(services.BuildServiceProvider());
                }
            });

            IMsalTokenCacheProvider msalTokenCacheProvider = serviceProvider.GetRequiredService <IMsalTokenCacheProvider>();

            msalTokenCacheProvider.Initialize(confidentialClientApp.UserTokenCache);
            msalTokenCacheProvider.Initialize(confidentialClientApp.AppTokenCache);
            return(confidentialClientApp);
        }
예제 #3
0
        /// <summary>
        /// Creates an MSAL confidential client application.
        /// </summary>
        private IConfidentialClientApplication BuildConfidentialClientApplication()
        {
            var    httpContext = CurrentHttpContext;
            var    request     = httpContext?.Request;
            string?currentUri  = null;

            if (!string.IsNullOrEmpty(_applicationOptions.RedirectUri))
            {
                currentUri = _applicationOptions.RedirectUri;
            }

            if (request != null && string.IsNullOrEmpty(currentUri))
            {
                currentUri = BuildCurrentUriFromRequest(httpContext !, request);
            }

            PrepareAuthorityInstanceForMsal();

            MicrosoftIdentityOptionsValidation.ValidateEitherClientCertificateOrClientSecret(
                _applicationOptions.ClientSecret,
                _microsoftIdentityOptions.ClientCertificates);

            try
            {
                var builder = ConfidentialClientApplicationBuilder
                              .CreateWithApplicationOptions(_applicationOptions)
                              .WithHttpClientFactory(_httpClientFactory)
                              .WithLogging(
                    Log,
                    ConvertMicrosoftExtensionsLogLevelToMsal(_logger),
                    enablePiiLogging: _applicationOptions.EnablePiiLogging)
                              .WithExperimentalFeatures();

                // The redirect URI is not needed for OBO
                if (!string.IsNullOrEmpty(currentUri))
                {
                    builder.WithRedirectUri(currentUri);
                }

                string authority;

                if (_microsoftIdentityOptions.IsB2C)
                {
                    authority = $"{_applicationOptions.Instance}{ClaimConstants.Tfp}/{_microsoftIdentityOptions.Domain}/{_microsoftIdentityOptions.DefaultUserFlow}";
                    builder.WithB2CAuthority(authority);
                }
                else
                {
                    authority = $"{_applicationOptions.Instance}{_applicationOptions.TenantId}/";
                    builder.WithAuthority(authority);
                }

                if (_microsoftIdentityOptions.ClientCertificates != null)
                {
                    X509Certificate2?certificate = DefaultCertificateLoader.LoadFirstCertificate(_microsoftIdentityOptions.ClientCertificates);
                    builder.WithCertificate(certificate);
                }

                IConfidentialClientApplication app = builder.Build();
                _application = app;
                // Initialize token cache providers
                _tokenCacheProvider.Initialize(app.AppTokenCache);
                _tokenCacheProvider.Initialize(app.UserTokenCache);
                return(app);
            }
            catch (Exception ex)
            {
                _logger.LogInformation(
                    ex,
                    IDWebErrorMessage.ExceptionAcquiringTokenForConfidentialClient);
                throw;
            }
        }