For the past couple of days, I've been reading up the documentation thoroughly to implement custom authorisation header support for Swashbuckle.AspNetCore 5.x.x and have been unable to propagate SwaggerUI to properly send API requests from the API docs to any of the APIs (The APIs get hit but it always fails at my Authorize attribute because the header key the contains the API Key is empty).
I've also stumbled upon these questions:
- SwaggerUI with .NetCore 3.0 bearer token authorization
- Authorization for JWT bearer in Swashbuckle .NET Core 2
- How to document API Key authentication using Swashbuckle.AspNetCore v5.0.0-rc2
I'm on 5.2.0 on all of Swashbuckle's packages with .NET Core 3.1.2.
Doesn't seem to work! :(
Here's my ConfigureServices
for Authentication, authorisation and Swagger DI
services.AddAuthentication(options =>
{
options.DefaultScheme = ApiKeyAuthenticationOptions.DefaultScheme;
options.DefaultAuthenticateScheme = ApiKeyAuthenticationOptions.DefaultScheme;
})
.AddScheme<ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>(
ApiKeyAuthenticationOptions.DefaultScheme, o => { });
services.AddAuthorization(options =>
{
var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(
ApiKeyAuthenticationOptions.DefaultScheme);
defaultAuthorizationPolicyBuilder =
defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
});
services.AddSwaggerGen(config =>
{
config.SwaggerDoc(GlobalApiVariables.CURRENT_API_VERSION, new OpenApiInfo {
Title = "XXXX API",
Version = GlobalApiVariables.CURRENT_API_REVISION.ToString()
});
config.EnableAnnotations();
// Adds "(Auth)" to the summary so that you can see which endpoints have Authorization
config.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
// or use the generic method, e.g. c.OperationFilter<AppendAuthorizeToSummaryOperationFilter<MyCustomAttribute>>();
// [SwaggerRequestExample] & [SwaggerResponseExample]
// version < 3.0 like this: c.OperationFilter<ExamplesOperationFilter>();
// version 3.0 like this: c.AddSwaggerExamples(services.BuildServiceProvider());
// version > 4.0 like this:
config.ExampleFilters();
config.OperationFilter<AddResponseHeadersFilter>(); // [SwaggerResponseHeader]
// Locate the XML file being generated by .NET Core
var filePath = Path.Combine(AppContext.BaseDirectory,
$"{Assembly.GetExecutingAssembly().GetName().Name}.xml");
config.IncludeXmlComments(filePath);
// Define the Api Key scheme that's in use (i.e. Implicit Flow)
config.AddSecurityDefinition(ApiKeyAuthenticationOptions.DefaultScheme, new OpenApiSecurityScheme
{
Description = "Testtest",
In = ParameterLocation.Header,
Name = ApiKeyAuthenticationOptions.HeaderKey,
Type = SecuritySchemeType.ApiKey,
Flows = new OpenApiOAuthFlows
{
Implicit = new OpenApiOAuthFlow
{
AuthorizationUrl = new Uri("/connect/validate", UriKind.Relative),
Scopes = new Dictionary<string, string>
{
{ "readAccess", "Access read operations" },
{ "writeAccess", "Access write operations" }
}
}
}
});
// add Security information to each operation for OAuth2
config.OperationFilter<SecurityRequirementsOperationFilter>();
config.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = ApiKeyAuthenticationOptions.DefaultScheme
}
},
new[] { "readAccess", "writeAccess" }
}
});
});
services.AddSwaggerExamplesFromAssemblies(Assembly.GetEntryAssembly());
And also, in Configure
I added:
app.UseSwagger(c =>
{
c.RouteTemplate = "/{documentName}/swagger.json";
});
app.UseSwaggerUI(c =>
{
c.DocumentTitle = "XXXXX Documentation";
c.RoutePrefix = "";
c.SwaggerEndpoint($"/{GlobalApiVariables.CURRENT_API_VERSION}/swagger.json",
$"XXXX v{GlobalApiVariables.CURRENT_API_REVISION}");
c.OAuthClientSecret(ApiKeyAuthenticationOptions.HeaderKey);
});
Here's ApiKeyAuthenticationOptions
if you require it:
public class ApiKeyAuthenticationOptions : AuthenticationSchemeOptions
{
public const string DefaultScheme = "API Key";
public string Scheme => DefaultScheme;
public string AuthenticationType = DefaultScheme;
public const string HeaderKey = "X-Api-Key";
}
Let me know what I'm doing wrong, and thank you so much ahead of time!