I'm using ASP.NET Core and NSwag to host and describe a new web service hosted in IIS with Windows Authentication.
Locally I run the web service using https, but when I deploy to a test environment the web service sits behind a load balancer with SSL-offloading. This means that even though the site appears to run under SSL in the browser, the actual binding in IIS is http. So my Swagger UI page (and swagger.json definition) describes the schemes supported as http.
I'd like the Schemes element in the Swagger.json that I use to read "https" instead of "http". Would anyone be able to help me find the property I need to set in my code to set the scheme manually?
{
x-generator: "NSwag v11.19.1.0 (NJsonSchema v9.10.72.0 (Newtonsoft.Json v11.0.0.0))",
swagger: "2.0",
info: {
title: "My API title",
description: "Provides access to data.",
version: "1.0.0"
},
host: "myhostname.net",
schemes: [
"http"
],
etc...
}
Boom. Got it!
Finally found an answer on Github and the following code did the trick:
app.UseSwaggerWithApiExplorer(config =>
{
//...other code omitted...
config.PostProcess = settings =>
{
settings.Schemes.Clear();
settings.Schemes.Add(NSwag.SwaggerSchema.Https);
};
});
EDIT:
for NSwag v12 use:
app.UseSwagger(configure => configure.PostProcess = (document, _) => document.Schemes = new[] { SwaggerSchema.Https });
My project was using NSwag v13 and the below worked for me.
app.UseOpenApi(a => {
a.PostProcess = (document, _) => {
document.Schemes = new[] { OpenApiSchema.Https, OpenApiSchema.Http };
};
});
Source:
https://github.com/RicoSuter/NSwag/issues/1545
Related
So, I followed the guidelines in the Microsoft Docs and this Medium article which propose that adding OIDC authentication to a Blazor WASM application should be easy as pie.
I already have a working OIDC-Server (Keycloak) which I have used for several Blazor Server applications successfully.
I then defined the needed properties in appsettings.json like this:
{
"OIDC": {
"Authority": "https://mykeycloakserver/auth/realms/master/",
"ClientId": "MyClientId",
"ClientSecret": "FooBarBaz-813361955dc3",
"DefaultScopes": [
"openid",
"profile",
"roles",
"offline_access"
],
"PostLogoutRedirectUri": "/",
"ResponseType": "code"
}
}
and added this to program.cs
builder.Services.AddOidcAuthentication(options =>
{
builder.Configuration.Bind("OIDC", options.ProviderOptions);
});
Application (and server API) starts, I click on Login and am greeted with this message:
It then does not matter whether I define the RedirectUri through appsetting.json or explicitly in program.cs like this:
options.ProviderOptions.RedirectUri = "https://localhost:7066/authentication/login-callback";
It always tells me that it's undefined. Setting a breakpoint after the configuration bind tells me that my settings are indeed picked up!
The complete program.cs:
using MyWASM.Client;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddHttpClient("AnliegenWASM.ServerAPI", client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
// Supply HttpClient instances that include access tokens when making requests to the server project
builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>().CreateClient("MyWASM.ServerAPI"));
builder.Services.AddOidcAuthentication(options =>
{
builder.Configuration.Bind("OIDC", options.ProviderOptions);
//options.ProviderOptions.RedirectUri = "https://localhost:7066/authentication/login-callback";
});
await builder.Build().RunAsync();
So, what am I missing?
I also ran into this problem. Double check the index.html page where the JS AuthenticationService is added.
I had it referencing the MSAL auth service:
<script src="_content/Microsoft.Authentication.WebAssembly.Msal/AuthenticationService.js"></script>
When it should have been:
<script src="_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"></script>
I have a blazor wasm application running on a subpath Apps/Genesis/
The problem is some DLL's are not being found:
The request is:
https://localhost:5001/Apps/Genesis/Apps/Genesis/_framework/Blazored.LocalStorage.dll
The request should be:
https://localhost:5001/Apps/Genesis/_framework/Blazored.LocalStorage.dll
app.MapWhen(
context =>
{
return context.Request.Path.StartsWithSegments("/Apps/Genesis");
},
genesis =>
{
// Define blazor files
genesis.UseBlazorFrameworkFiles("/Apps/Genesis");
// Access static files (Ex.: images, dll's) - Used twice because it's on the microsoft docs example
genesis.UseStaticFiles();
genesis.UseStaticFiles("/Apps/Genesis");
// Apply routing for UseEndpoints
genesis.UseRouting();
// Especify Routes
genesis.UseEndpoints(
endpoints =>
{
endpoints.MapControllers();
endpoints.MapFallbackToFile("Apps/Genesis/{{*path:nonfile}}", "Apps/Genesis/index.html");
});
});
Having the below code to configure in Startup.cs
Variables.
private const string SwaggerDocumentVersionName = "v1";
private static string SwaggerDocumentServiceName => $"Users API({SwaggerDocumentVersionName})";
ConfigureServices method.
services.AddSwaggerGen(c =>
{
c.SwaggerDoc(
SwaggerDocumentVersionName,
new OpenApiInfo
{
Title = SwaggerDocumentServiceName,
Version = $"{SwaggerDocumentVersionName}"
});
});
Configure method.
app.UseSwagger(c =>
{
c.RouteTemplate = "/swagger/{documentName}/swagger.json";
});
app.UseSwaggerUI(c =>
{
c.RoutePrefix = "swagger/ui";
c.SwaggerEndpoint($"/swagger/{SwaggerDocumentVersionName}/swagger.json", SwaggerDocumentServiceName);
});
When running locally (https://localhost:5001/swagger/ui resolved to https://localhost:5001/swagger/ui/index.html) definition is loaded correctly and everything seems fine.
Deploying the service to AWS Lambda as ASP.NET Core REST API and navigating to the URL (https://DNS_URL/API_PREFIX/swagger/ui resolved to https://DNS_URL/API_PREFIX/swagger/ui/index.html)it shows the below error loading the JSON definition.
The interesting part is that if you navigate to the JSON definition route (https://DNS_URL/API_PREFIX/swagger/v1/swagger.json) it shows the definition.
The main URL for the API you have released on lambda is https://DNS_URL/API_PREFIX/
Swagger UI needs to fetch the swagger.json file in order for it to work, and for your localhost it is working correctly since https://localhost:5001/swagger/v1/swagger.json is a valid endpoint
(*you have no prefix here)
And the version deployed to lambda is trying to fetch this swagger.json file under
https://DNS_URL/swagger/v1/swagger.json - without your API_PREFIX, thus it's returning 404, not found and swagger ui is displaying the Error message.
Quick fix, which you might apply, that I think would work:
app.UseSwaggerUI(c =>
{
c.RoutePrefix = "swagger/ui";
c.SwaggerEndpoint($"{env.IsDevelopment() ? "" : API_PREFIX}/swagger/{SwaggerDocumentVersionName}/swagger.json", SwaggerDocumentServiceName);
});
Where the API_PREFIX is a string starting with '/'
i'm using swagger ui in my asp.net mvc
Swashbuckle v 5.6
asp.net v 4.8
on local machine everythink working successfully but unfortunately after deploy website to cloud, swagger not load static content, but wen i navigate to these resources using chrome it's loadded successfully
i config swagger using:
public static void Register()
{
var thisAssembly = typeof(SwaggerConfig).Assembly;
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.Schemes(new[] { "http", "https" });
c.IgnoreObsoleteActions();
c.SingleApiVersion("v1", "Console - API");
c.ApiKey("auth")
.Description("API Key Authentication")
.Name("auth")
.In("header");
c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
c.IncludeXmlComments(String.Format(#"{0}\bin\docs.xml", System.AppDomain.CurrentDomain.BaseDirectory));
c.UseFullTypeNameInSchemaIds();
})
.EnableSwaggerUi(c =>
{
c.DocumentTitle("Console - API");
c.EnableApiKeySupport("auth", "header");
c.InjectJavaScript(thisAssembly, "Console.API.Assets.Swagger.SwashbuckleCustomAuth.js");
c.InjectStylesheet(thisAssembly, "Console.API.Assets.Swagger.SwashbuckleCustomStyle.css");
});
}
Do i miss any thing? dose https effects swagger load static files?
pss: i don't think this issue related to iis because i have placed a static file in root folder of the website and i was able to load it
The IIS was block simultaneous requests, and the solution was by increment maximum concurrent connections in site advance settings in IIS
I am using ASP.NET Boilerplate v2.0.1 with .NET Core and Angular 2 project template.
I have multiple modules in my project that are currently served using same API endpoint. Please note, in the future I will have separate API endpoint for an individual module.
As the API endpoint is same for every module, the service proxy which is generated through NSwag will have all the modules' services.
I am having a requirement to have proxy generated based on an individual module, so for this, I thought of accomplishing using API versioning. So instead of v1, v2 etc., I will append the module name.
I have the following code:
Configuration.Modules.AbpAspNetCore()
.CreateControllersForAppServices(
typeof(Module).GetAssembly(),
"modulename"
);
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("module1", new Info { Title = "Module 1", Version = "module1" });
options.SwaggerDoc("module2", new Info { Title = "Module 2", Version = "module2" });
}
app.UseSwagger(options =>
{
options.RouteTemplate = "swagger/{documentName}/swagger.json";
});
// Enable middleware to serve swagger-ui assets (HTML, JS, CSS etc.)
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/module1/swagger.json", "Module 1");
options.SwaggerEndpoint("/swagger/module2/swagger.json", "Module 2");
});
This way, I am able to generate two endpoints as follows:
http://localhost:5000/swagger/module1/swagger.json
http://localhost:5000/swagger/module2/swagger.json
But both are having all the modules' information.
Please correct me or suggest a way to achieve the functionality.
It looks like you are using swashbuckle and not NSwag to generate your swagger docs. There are multiple ways to separate your docs by version, see swashbuckle documentation https://github.com/domaindrivendev/Swashbuckle.AspNetCore. The default method is to use your startup configs that you have above and decorate your methods with the corresponding ApiExplorer group name. The group name needs to match the first argument specified in the swaggerdoc config.
[ApiExplorerSettings(GroupName = "module1")] //Module 1 Method
You are also missing an 'e' in module for the second swagger endpoint.
see example: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/4bbf5cacd6ad0817b9015d699c559fd5c1cedf0d/test/WebSites/MultipleVersions/Startup.cs
To add multiple source edit the SwaggerUIOptions.
For example:
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("http://<ip1>:<port>/swagger/v1/swagger.json", "ServiceName1");
c.SwaggerEndpoint("http://<ip2>:<port>/swagger/v1/swagger.json", "ServiceName2");
});