/// <summary>
        /// Services configuration
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public static IServiceCollection AddSharedKernelOpenApi(this IServiceCollection services, IConfiguration configuration)
        {
            var openApiOptions = new OpenApiOptions();

            configuration.GetSection(nameof(OpenApiOptions)).Bind(openApiOptions);
            services.Configure <OpenApiOptions>(configuration.GetSection(nameof(OpenApiOptions)));

            var openIdOptions = new OpenIdOptions();

            configuration.GetSection(nameof(OpenIdOptions)).Bind(openIdOptions);

            services.AddSwaggerGenNewtonsoftSupport();

            services.AddFluentValidationRulesToSwagger();

            services.AddSwaggerGen(swaggerGenOptions =>
            {
                swaggerGenOptions.SwaggerDoc("v1", new OpenApiInfo {
                    Title = openApiOptions.Title, Version = "v1"
                });

                swaggerGenOptions.SchemaFilter <RequireValueTypePropertiesSchemaFilter>();

                swaggerGenOptions.DescribeAllParametersInCamelCase();

                var xmlPath = swaggerGenOptions.IncludeXmlComments(openApiOptions, true);

                swaggerGenOptions.AddSecurityDefinition(openIdOptions, openApiOptions);

                swaggerGenOptions.AddEnumsWithValuesFixFilters(services, xmlPath);

                swaggerGenOptions.OperationFilter <SecurityRequirementsOperationFilter>();
            });

            return(services);
        }
        /// <summary>
        /// Add one or more "securityDefinitions", describing how your API is protected, to the generated Swagger
        /// </summary>
        /// <param name="swaggerGenOptions"></param>
        /// <param name="openIdOptions"><see cref="OpenIdOptions"/></param>
        /// <param name="openApiOptions"><see cref="OpenApiOptions"/></param>
        public static void AddSecurityDefinition(this SwaggerGenOptions swaggerGenOptions, OpenIdOptions openIdOptions, OpenApiOptions openApiOptions)
        {
            var authority = openApiOptions?.Authority ?? openIdOptions?.Authority;

            if (string.IsNullOrWhiteSpace(authority))
            {
                return;
            }

            swaggerGenOptions.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
            {
                Type  = SecuritySchemeType.OAuth2,
                Flows = new OpenApiOAuthFlows
                {
                    Password = new OpenApiOAuthFlow
                    {
                        AuthorizationUrl = new Uri(authority),
                        TokenUrl         = new Uri(authority + "/connect/token"),
                        Scopes           = openIdOptions.Scopes.ToDictionary(s => s.Name, s => s.DisplayName)
                    }
                }
            });

            swaggerGenOptions.AddSecurityRequirement(new OpenApiSecurityRequirement
            {
                {
                    new OpenApiSecurityScheme
                    {
                        Reference = new OpenApiReference {
                            Type = ReferenceType.SecurityScheme, Id = "oauth2"
                        }
                    },
                    new[] { openIdOptions.Audience }
                }
            });
        }
        /// <summary>
        /// Inject human-friendly descriptions for Operations, Parameters and Schemas based on XML Comment files
        /// </summary>
        /// <param name="swaggerGenOptions"></param>
        /// <param name="openApiOptions"><see cref="OpenApiOptions"/></param>
        /// <param name="includeControllerXmlComments">
        /// Flag to indicate if controller XML comments (i.e. summary) should be used to assign Tag descriptions.
        /// Don't set this flag if you're customizing the default tag for operations via TagActionsBy.
        /// </param>
        public static string IncludeXmlComments(this SwaggerGenOptions swaggerGenOptions, OpenApiOptions openApiOptions,
                                                bool includeControllerXmlComments = false)
        {
            string xmlPath = null;

            if (openApiOptions.XmlDocumentationFiles != default && openApiOptions.XmlDocumentationFiles.Any())
            {
                xmlPath = swaggerGenOptions.IncludeXmlComments(openApiOptions.XmlDocumentationFiles, includeControllerXmlComments);
            }
            else if (!string.IsNullOrWhiteSpace(openApiOptions.XmlDocumentationFile))
            {
                xmlPath = Path.Combine(AppContext.BaseDirectory, openApiOptions.XmlDocumentationFile);
                swaggerGenOptions.IncludeXmlComments(xmlPath, includeControllerXmlComments);
            }

            return(xmlPath);
        }