Skip to content

v2: Consider changing definition of OpenApiSecurityRequirement #1974

Open
@captainsafia

Description

The OpenApiSecurityRequirement type is currently defined as Dictionary<OpenApiSecurityScheme, IList<string>>.

For v2, we should consider taking a breaking change to define it as Dictionary<string, IList<string>> and support referencing the security scheme by the name used in the components hierarchy in the document.

The OpenAPI specification states that security requirements should an association between { string: string[] } so it strikes me that we can update the type definition to align with this.

This would simplify the code that users have to write when setting security requirements in documents. Instead of:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.OpenApi.Models;

public static class OpenApiOptionsExtensions
{
    public static OpenApiOptions AddBearerTokenAuthentication(this OpenApiOptions options)
    {
        var scheme = new OpenApiSecurityScheme()
        {
            Type = SecuritySchemeType.Http,
            Name = IdentityConstants.BearerScheme,
            Scheme = "Bearer",
            Reference = new()
            {
                Type = ReferenceType.SecurityScheme,
                Id = IdentityConstants.BearerScheme
            }
        };
        options.AddDocumentTransformer((document, context, cancellationToken) =>
        {
            document.Components ??= new();
            document.Components.SecuritySchemes.Add(IdentityConstants.BearerScheme, scheme);
            return Task.CompletedTask;
        });
        options.AddOperationTransformer((operation, context, cancellationToken) =>
        {
            if (context.Description.ActionDescriptor.EndpointMetadata.OfType<IAuthorizeData>().Any())
            {
                operation.Security = [new() { [scheme] = [] }];
            }
            return Task.CompletedTask;
        });
        return options;
    }
}

Users can write:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.OpenApi.Models;

public static class OpenApiOptionsExtensions
{
    public static OpenApiOptions AddBearerTokenAuthentication(this OpenApiOptions options)
    {
        var scheme = new OpenApiSecurityScheme()
        {
            Type = SecuritySchemeType.Http,
            Name = IdentityConstants.BearerScheme,
            Scheme = "Bearer",
            Reference = new()
            {
                Type = ReferenceType.SecurityScheme,
                Id = IdentityConstants.BearerScheme
            }
        };
        options.AddDocumentTransformer((document, context, cancellationToken) =>
        {
            document.Components ??= new();
            document.Components.SecuritySchemes.Add(IdentityConstants.BearerScheme, scheme);
            return Task.CompletedTask;
        });
        options.AddOperationTransformer((operation, context, cancellationToken) =>
        {
            if (context.Description.ActionDescriptor.EndpointMetadata.OfType<IAuthorizeData>().Any())
            {
                operation.Security = [new() { "Bearer" = [] }];
            }
            return Task.CompletedTask;
        });
        return options;
    }
}

Is there a particular reason the object model inlines the SecurityScheme instead of using a name reference?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Labels

priority:p2Medium. Generally has a work-around and a smaller sub-set of customers is affected. SLA <=30 daysstatus:waiting-for-internal-feedbackNeeds internal stakeholder(s) input to resolve

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions