-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Open
Labels
DocsThis issue tracks updating documentationThis issue tracks updating documentationarea-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcfeature-openapigood first issueGood for newcomers.Good for newcomers.help wantedUp for grabs. We would accept a PR to help resolve this issueUp for grabs. We would accept a PR to help resolve this issue
Milestone
Description
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
documentation shows you can do something like this
internal sealed class BearerSecuritySchemeTransformer(IAuthenticationSchemeProvider authenticationSchemeProvider) : IOpenApiDocumentTransformer
{
public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken)
{
var authenticationSchemes = await authenticationSchemeProvider.GetAllSchemesAsync();
if (authenticationSchemes.Any(authScheme => authScheme.Name == "Bearer"))
{
// Add the security scheme at the document level
var requirements = new Dictionary<string, OpenApiSecurityScheme>
{
["Bearer"] = new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "bearer", // "bearer" refers to the header name here
In = ParameterLocation.Header,
BearerFormat = "Json Web Token"
}
};
document.Components ??= new OpenApiComponents();
document.Components.SecuritySchemes = requirements;
// Apply it as a requirement for all operations
foreach (var operation in document.Paths.Values.SelectMany(path => path.Operations))
{
operation.Value.Security.Add(new OpenApiSecurityRequirement
{
[new OpenApiSecurityScheme { Reference = new OpenApiReference { Id = "Bearer", Type = ReferenceType.SecurityScheme } }] = Array.Empty<string>()
});
}
}
}
}
Which applies the security schema for all the endpoints, but it doesnt show a way to skip the endpoints or controllers that have the AllowAnonymousAttribute applied
for now the only workaround I have found is by using Tags, but it is a little hacky.
internal sealed class BearerSecuritySchemeTransformer(
IAuthenticationSchemeProvider authenticationSchemeProvider
) : IOpenApiDocumentTransformer
{
private const string SecuritySchemeName = "Bearer";
private const string AnonymousTagName = "Anonymous";
public async Task TransformAsync(
OpenApiDocument document,
OpenApiDocumentTransformerContext context,
CancellationToken cancellationToken
)
{
var authenticationSchemes = await authenticationSchemeProvider.GetAllSchemesAsync();
bool hasBearerScheme = authenticationSchemes.Any(authScheme => authScheme.Name == SecuritySchemeName);
if (hasBearerScheme)
{
document.Components ??= new OpenApiComponents();
document.Components.SecuritySchemes ??= new Dictionary<string, OpenApiSecurityScheme>();
// Only add if it doesn't exist - avoid conflicts if multiple transformers run
if (!document.Components.SecuritySchemes.ContainsKey(SecuritySchemeName))
{
document.Components.SecuritySchemes.Add(SecuritySchemeName, new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT",
Name = "Authorization",
In = ParameterLocation.Header,
});
}
}
// Remove Anonymous tag from the tags collection if it exists
var anonymousTag = document.Tags.FirstOrDefault(t => t.Name == AnonymousTagName);
if (anonymousTag != null)
{
document.Tags.Remove(anonymousTag);
}
foreach (var path in document.Paths.Values)
{
foreach (var operation in path.Operations)
{
// Check if operation has Anonymous tag
var anonymousTagInOperation = operation.Value.Tags.FirstOrDefault(t => t.Name == AnonymousTagName);
if (anonymousTagInOperation != null)
{
// Remove Anonymous tag from the operation
operation.Value.Tags.Remove(anonymousTagInOperation);
// Skip adding security requirement
continue;
}
// Add security requirement for non-anonymous operations
operation.Value.Security.Add(new OpenApiSecurityRequirement
{
[new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Id = SecuritySchemeName,
Type = ReferenceType.SecurityScheme
}
}] = Array.Empty<string>()
});
}
}
}
}
Expected Behavior
Please show an example on how to skip security requirements for controllers / endpoints that have the AllowAnonymousAttribute applied
Thanks.
Steps To Reproduce
The steps to repro the issue are at https://learn.microsoft.com/en-us/aspnet/core/fundamentals/openapi/customize-openapi?view=aspnetcore-9.0#use-document-transformers
Exceptions (if any)
No response
.NET Version
9.0.104
Anything else?
No response
Metadata
Metadata
Assignees
Labels
DocsThis issue tracks updating documentationThis issue tracks updating documentationarea-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcfeature-openapigood first issueGood for newcomers.Good for newcomers.help wantedUp for grabs. We would accept a PR to help resolve this issueUp for grabs. We would accept a PR to help resolve this issue