Esempio n. 1
0
        public static NaosServicesContextOptions AddSwaggerDocumentation(
            this NaosServicesContextOptions naosOptions)
        {
            EnsureArg.IsNotNull(naosOptions, nameof(naosOptions));

            naosOptions.Context.Services
            .AddSwaggerDocument((c, sp) =>     // TODO: replace with .AddOpenApiDocument, but currently has issues with example model generation in UI
            {
                // TODO: AddNaos.AddSwaggerDocument() ^^^^
                c.SerializerSettings = DefaultJsonSerializerSettings.Create();
                // find all processors which are registerd by various naos features (Command RequestDispatcher/ControllerRegistrations)
                foreach (var documentProcessor in sp.GetServices <IDocumentProcessor>())
                {
                    c.DocumentProcessors.Add(documentProcessor);
                }

                foreach (var operationProcessor in sp.GetServices <IOperationProcessor>())
                {
                    c.OperationProcessors.Add(operationProcessor);
                }

                //c.DocumentProcessors.Add(
                //    new SecurityDefinitionAppender("Bearer", new OpenApiSecurityScheme
                //    {
                //        Name = "Authorization",
                //        Description = "Authorization header using the ApiKey scheme. Example: \"Authorization: ApiKey {value}\"",
                //        In = NSwag.OpenApiSecurityApiKeyLocation.Header,
                //        Type = NSwag.OpenApiSecuritySchemeType.ApiKey // Oauth2/OIDC?
                //    }));

                c.OperationProcessors.Add(new ApiVersionProcessor());
                c.PostProcess = document =>
                {
                    var descriptor               = sp.GetService <Foundation.ServiceDescriptor>();
                    document.Info.Version        = descriptor?.Version.EmptyToNull() ?? "v1";
                    document.Info.Title          = descriptor?.Name.EmptyToNull() ?? "Naos";
                    document.Info.Description    = descriptor?.Tags.ToString(", ").EmptyToNull() ?? "Naos";
                    document.Info.TermsOfService = "None";
                    document.Info.Contact        = new NSwag.OpenApiContact
                    {
                        Name  = "Naos",
                        Email = string.Empty,
                        Url   = "https://github.com/vip32/Naos"
                    };
                };

                if (true)     // if option.includeSecurityHeader
                {
                    var provider = sp.GetService <IAuthenticationSchemeProvider>();
                    if (provider?.GetDefaultChallengeSchemeAsync().Result?.Name == AuthenticationKeys.OidcScheme)
                    {
                        c.AddSecurity("Oauth2", new NSwag.OpenApiSecurityScheme
                        {
                            AuthorizationUrl = "https://global-keycloak.azurewebsites.net/auth/realms/master/protocol/openid-connect/auth",
                            Description      = "Authorization header using the Oauth2 Bearer scheme. Example: \"Authorization: Bearer {token}\"",
                            Name             = "Authorization",
                            Flow             = NSwag.OpenApiOAuth2Flow.Implicit,
                            In   = NSwag.OpenApiSecurityApiKeyLocation.Header,
                            Type = NSwag.OpenApiSecuritySchemeType.OAuth2
                        });
                        c.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("Oauth2"));

                        c.AddSecurity("Oidc", new NSwag.OpenApiSecurityScheme
                        {
                            Scheme           = "Bearer",
                            OpenIdConnectUrl = "https://global-keycloak.azurewebsites.net/auth/realms/master/.well-known/openid-configuration",
                            //AuthorizationUrl = "https://global-keycloak.azurewebsites.net/auth/realms/master/protocol/openid-connect/auth",
                            Description = "Authorization header using the Oidc Bearer scheme. Example: \"Authorization: Bearer {token}\"",
                            Name        = "Authorization",
                            Flow        = NSwag.OpenApiOAuth2Flow.Implicit,
                            In          = NSwag.OpenApiSecurityApiKeyLocation.Header,
                            Type        = NSwag.OpenApiSecuritySchemeType.OpenIdConnect // Oauth2/OIDC?,
                        });
                        c.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("Oidc"));

                        //c.AddSecurity("JWT", new NSwag.OpenApiSecurityScheme
                        //{
                        //    //Schema="Bearer" << has to be added manually in the Auth text box (swaggerui) https://github.com/RicoSuter/NSwag/issues/869
                        //    Description = "Authorization header using a JWT token. Example: \"Authorization: Bearer {jwt}\"",
                        //    Name = "Authorization",
                        //    In = NSwag.OpenApiSecurityApiKeyLocation.Header,
                        //    Type = NSwag.OpenApiSecuritySchemeType.ApiKey
                        //});
                        //c.OperationProcessors.Add(new OperationSecurityScopeProcessor("JWT"));
                    }
                    else if (provider?.GetDefaultChallengeSchemeAsync().Result?.Name == AuthenticationKeys.ApiKeyScheme)
                    {
                        c.AddSecurity(AuthenticationKeys.ApiKeyScheme, new NSwag.OpenApiSecurityScheme
                        {
                            Description = "Authorization header using the ApiKey scheme. Example: \"Authorization: ApiKey {key}\"",
                            Name        = "ApiKey",
                            In          = NSwag.OpenApiSecurityApiKeyLocation.Header, // TODO: also allow the auth header to be sent in the querystring
                            Type        = NSwag.OpenApiSecuritySchemeType.ApiKey
                        });
                        c.OperationProcessors.Add(new OperationSecurityScopeProcessor(AuthenticationKeys.ApiKeyScheme));
                    }
                    else if (provider?.GetDefaultChallengeSchemeAsync().Result?.Name == AuthenticationKeys.BasicScheme)
                    {
                        c.AddSecurity(AuthenticationKeys.BasicScheme, new NSwag.OpenApiSecurityScheme
                        {
                            Scheme      = "Basic",
                            Description = "Authorization header using the Basic scheme. Example: \"Basic: {credentials}\"",
                            Name        = "Authorization",
                            In          = NSwag.OpenApiSecurityApiKeyLocation.Header, // TODO: also allow the auth header to be sent in the url https://en.wikipedia.org/wiki/Basic_access_authentication
                            Type        = NSwag.OpenApiSecuritySchemeType.Basic
                        });
                        c.OperationProcessors.Add(new OperationSecurityScopeProcessor(AuthenticationKeys.BasicScheme));
                    }
                }
            });

            naosOptions.Context.Messages.Add("naos services builder: swagger documentation added");
            //naosOptions.Context.Services.AddSingleton(new NaosFeatureInformation { Name = "Swagger", Description = "Documentation", EchoRoute = "naos/swagger/echo" });

            return(naosOptions);
        }
Esempio n. 2
0
        public static NaosServicesContextOptions AddWebApi(
            this NaosServicesContextOptions naosOptions,
            Action <NaosMvcOptions> optionsAction = null,
            Action <IMvcCoreBuilder> optionsMvc   = null)
        {
            var options = new NaosMvcOptions();

            optionsAction?.Invoke(options);

            naosOptions.Context.Services.AddHttpContextAccessor();
            //mvcBuilder.Services.AddSingleton<IActionContextAccessor, ActionContextAccessor>(); // needed for GetUrlHelper (IUrlHelperFactory below)
            //mvcBuilder.Services.AddScoped(sp =>
            //{
            //    // enables usage of IUrlHelper https://benfoster.io/blog/injecting-urlhelper-in-aspnet-core-mvc
            //    var actionContext = sp.GetRequiredService<IActionContextAccessor>()?.ActionContext;
            //    if (actionContext == null)
            //    {
            //        throw new ArgumentException("UrlHelper needs an ActionContext, which is usually available in MVC components (Controller/PageModel/ViewComponent)");
            //    }

            //    var factory = sp.GetRequiredService<IUrlHelperFactory>();
            //    return factory?.GetUrlHelper(actionContext);
            //});

            var mvcBuilder = naosOptions.Context.Services
                             //.AddLogging()
                             .AddMvcCore();

            //jsonSerializer ??= JsonSerializer.Create(DefaultJsonSerializerSettings.Create());

            // add the generic repository controllers for all registrations (AddEndpoint)
            if (!options.ControllerRegistrations.IsNullOrEmpty())
            {
                mvcBuilder
                .AddMvcOptions(o =>
                {
                    //o.Filters.Add(new AuthorizeFilter(new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build())); // https://tahirnaushad.com/2017/08/28/asp-net-core-2-0-mvc-filters/ or use controller attribute (Authorize)
                    o.Filters.Add <OperationCancelledExceptionFilterAttribute>();
                    o.Conventions.Add(new GeneratedControllerRouteConvention());
                })
                .ConfigureApplicationPartManager(o => o
                                                 .FeatureProviders.Add(
                                                     new GenericRepositoryControllerFeatureProvider(
                                                         options.ControllerRegistrations)));

                mvcBuilder.Services.AddSingleton <IOperationProcessor>(new GenericRepositoryControllerOperationProcessor()); // needed for swagger generation (for each controller registration)
            }
            else
            {
                mvcBuilder.AddMvcOptions(o => { });
                //.AddDataAnnotations()
                //.AddApiExplorer()
                //.AddAuthorization();
            }

            optionsMvc?.Invoke(mvcBuilder);

            //mvcBuilder.AddJsonOptions(o => o.AddDefaultJsonSerializerSettings(options.JsonSerializerSettings));
            mvcBuilder.AddControllersAsServices(); // needed to resolve controllers through di https://andrewlock.net/controller-activation-and-dependency-injection-in-asp-net-core-mvc/
#if NETCOREAPP3_1
            var serializerSettings = DefaultJsonSerializerSettings.Create();
            naosOptions.Context.Services.AddControllers().AddNewtonsoftJson(x => SetSerializerSettings(x, serializerSettings));
            naosOptions.Context.Services.AddControllersWithViews().AddNewtonsoftJson(x => SetSerializerSettings(x, serializerSettings));
            naosOptions.Context.Services.AddRazorPages().AddNewtonsoftJson(x => SetSerializerSettings(x, serializerSettings));
#endif

            return(naosOptions);
        }