Closed odinnou closed 5 years ago
I think the configuration for Swagger UI 3 is not yet completely set in the served index.html:
https://github.com/RSuter/NSwag/blob/master/src/NSwag.AspNetCore/SwaggerUi3/index.html#L108
Compare with Swagger UI 2:
https://github.com/RSuter/NSwag/blob/master/src/NSwag.AspNetCore/SwaggerUi/index.html#L59
Looks good to me:
is a parameter missing?
Hi,
According to the description, seems that the issue is only when trying to send the header with the token, I faced something similar, and the issue was that I didn't include the OperationProcessor in the GeneratorSettings.
In Short, adding this line would help you:
settings.GeneratorSettings.OperationProcessors.Add(new OperationSecurityScopeProcessor("TEST_HEADER"));
Hope it helps.
Cheers!
Ah ok, this is documented here: https://github.com/RSuter/NSwag/wiki/Middlewares#enable-authorization-in-generator-and-swagger-ui
Please improve it if it was not clear.
Can we close?
Still have same issue, Ui3 correctly show SwaggerSecuritySchemeType.ApiKey but doesn't pass it in execute.
appBuilder.UseSwagger(typeof(Startup).Assembly,t =>
{
t.PostProcess = document =>
{
document.Info.Title = "title";
document.Info.Description = "desc";
document.SecurityDefinitions.Add("X-ApiKey", new SwaggerSecurityScheme
{
Type = SwaggerSecuritySchemeType.ApiKey,
Scheme = "X-ApiKey",
In=SwaggerSecurityApiKeyLocation.Header,
Name="X-ApiKey"
});
};
});
appBuilder.UseSwaggerUi3(s =>
{
s.GeneratorSettings.DocumentProcessors.Add(
new SecurityDefinitionAppender("X-ApiKey", new SwaggerSecurityScheme
{
Type = SwaggerSecuritySchemeType.ApiKey,
Name = "X-ApiKey",
In = SwaggerSecurityApiKeyLocation.Header,
Description = "API key for request authorization."
}));
s.GeneratorSettings.OperationProcessors.Add(new OperationSecurityScopeProcessor("X-ApiKey"));
});
but header doesn't passs after executing nor persist in curl. I use Owin. How it can be fixed?
I have the same issue as dmandreev: the UI correctly provides mechanism for setting an API Key value, but it does not actually pass that value in the HTTP header when making requests with Swagger UI test harness (v3).
Going back to the older version of the UI still appears to work.
Strange. Which version works?
As indicated at the top of this thread. When using (the now marked as obsolete) UseSwaggerUi, the process works (tho VS2017 nags about using obsolete methods). When switching to UseSwaggerUi3 and modifying the configuration according to previous findings, it still will not send the value in the Http Headers.
I am using version 12.0.4 with ASP .NET Core 2.2
Sample Code:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddHealthChecks();
services.AddSwaggerDocument(settings =>
{
settings.DocumentName = "swagger";
//add UI option for setting API Key in the Swagger UI
settings.DocumentProcessors.Add(new SecurityDefinitionAppender("EITKey", new SwaggerSecurityScheme
{
Type = SwaggerSecuritySchemeType.ApiKey,
Name = "EITKey",
In = SwaggerSecurityApiKeyLocation.Header,
Description = "EITKey"
}));
settings.PostProcess = document =>
{
document.Info.Version = "v1";
};
}).AddOpenApiDocument(document =>
{
//not sure I need this.
document.DocumentProcessors.Add(
new SecurityDefinitionAppender("EITKey", new SwaggerSecurityScheme
{
Type = SwaggerSecuritySchemeType.ApiKey,
Name = "EITKey",
In = SwaggerSecurityApiKeyLocation.Header
})
);
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//validate requests contain the API Key in the HTTP Header
app.UseAPIKeyMiddleware();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseMvc();
app.UseHealthChecks("/health");
app.UseSwagger();
app.UseSwaggerUi3();
}
I've just setup like that and it works fine:
services.AddSwaggerDocument( c =>
{
c.DocumentName = "apidocs";
c.Title = "Sample API";
c.Version = "v1";
c.Description = "The sample API documentation description.";
c.DocumentProcessors.Add(new SecurityDefinitionAppender("APIKey", new SwaggerSecurityScheme
{
Type = SwaggerSecuritySchemeType.ApiKey,
Name = "APIKey",
In = SwaggerSecurityApiKeyLocation.Header,
Description = "APIKey"
}));
c.OperationProcessors.Add(new OperationSecurityScopeProcessor("APIKey"));
});
I've just setup like that and it works fine:
services.AddSwaggerDocument( c => { c.DocumentName = "apidocs"; c.Title = "Sample API"; c.Version = "v1"; c.Description = "The sample API documentation description."; c.DocumentProcessors.Add(new SecurityDefinitionAppender("APIKey", new SwaggerSecurityScheme { Type = SwaggerSecuritySchemeType.ApiKey, Name = "APIKey", In = SwaggerSecurityApiKeyLocation.Header, Description = "APIKey" })); c.OperationProcessors.Add(new OperationSecurityScopeProcessor("APIKey")); });
It worked for me in local system. Thanks !
Maybe someone can update the wiki with this information?
I have added this to the wiki
If someone still experiencing this issue, especially in Owin environment, (NSwag13), solution is simple.
Pay attention that class or methods decorated with [AuthorizeAttribute] - it's checked by standard OperationSecurityScopeProcessor.
In my case, it's dosen't work cause of use custom attribute.
So you need your custom IOperationProcessor
public class WaveOperationSecurityScopeProcessor : IOperationProcessor
{
private readonly string _name;
public WaveOperationSecurityScopeProcessor() : this("Bearer")
{
}
public WaveOperationSecurityScopeProcessor(string name)
{
_name = name;
}
public bool Process(OperationProcessorContext context)
{
if (context.OperationDescription.Operation.Security == null)
{
context.OperationDescription.Operation.Security = new List<OpenApiSecurityRequirement>();
}
var scopes = GetScopes(context.OperationDescription, context.MethodInfo);
if (scopes != null)
{
context.OperationDescription.Operation.Security.Add(new OpenApiSecurityRequirement
{
{ _name, scopes }
});
}
return true;
}
protected virtual IEnumerable<string> GetScopes(OpenApiOperationDescription operationDescription, MethodInfo methodInfo)
{
var allAttributes = methodInfo.GetCustomAttributes().Concat(
methodInfo.DeclaringType.GetTypeInfo().GetCustomAttributes());
var authorizeAttributes = allAttributes.Where(a => a.GetType().Name == "WebApiUserAuthenticatedAttribute").ToList();
if (!authorizeAttributes.Any())
{
return null;
}
return Enumerable.Empty<string>();
}
}
In my case there is no scopes, so I just return empty array.
Second step is to add your customized GeneratorSettings.OperationProcessors before PostProcess. ( Or yuse OperationSecurityScopeProcessor with [AuthorizeAttribute] on ApiController methods)
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
app.UseSwagger(typeof(Startup).Assembly, t =>
{
t.GeneratorSettings.OperationProcessors.Add(new WaveOperationSecurityScopeProcessor("X-ApiKey"));
t.PostProcess = document =>
{
document.SchemaType = NJsonSchema.SchemaType.Swagger2;
document.Info.Title = "Hello Api Key!";
document.Info.Version = ServicesController.ApplicationCIVersionStatic();
document.SecurityDefinitions.Add("X-ApiKey", new OpenApiSecurityScheme
{
Type = OpenApiSecuritySchemeType.ApiKey,
Scheme = "X-ApiKey",
In = OpenApiSecurityApiKeyLocation.Header,
Name = "X-ApiKey"
});
};
});
app.UseSwaggerUi3(typeof(Startup).GetTypeInfo().Assembly, s=>
{
s.GeneratorSettings.DefaultUrlTemplate = "api/{controller}/{action}";
});
// rest of init
}
Now you'l see nice padlock icons in Ui3 with security protected methids , and correct curl strings with Api-Key header values.
Hope that help
Hello! In order to transmit header value to all my APIs, I used settings.GeneratorSettings.DocumentProcessors.Add(new SecurityDefinitionAppender with app.UseSwaggerUi.
In that way, all works like a charm !
curl -X GET --header 'Accept: text/html' --header 'TEST_HEADER: testvalue' 'http://localhost:60047/api/v2/users'
actionContext.HttpContext.Request.Headers["TEST_HEADER"] = "testvalue"
Then I try to update to UseSwaggerUi3 (because it's better)
But now, the header is not sent :(
curl -X GET "http://localhost:60047/api/v2/users" -H "accept: application/json"
actionContext.HttpContext.Request.Headers["TEST_HEADER"] = {}
I use : NSwag.AspNetCore Version=11.17.2
Thank you in advance, and if you have another method to send headers globally it could be great :)
Rémi