Open pfeigl opened 5 years ago
This can be partially solved by #2304, because than I could disable the global security and add security on a "per operation" basis for all operations and skip those which do not require security.
However this is not ideal and I'd prefer to have security on a global level and disable for single operations.
On another note: The actuall AllowAnonymous Support would have been created in #1933, but I think even with the PR it would not work right now because of the resulting JSON
Is this even possible with openapi (disable global security)?
Try to write a custom document/operation processor to get to the desired document. Then we can discuss implementing it out-of-the-box.
Hi. I would also like the ability to define security at the global level to apply to all operations and then only override the one or two operations that allows anonymous access. As @pfeigl mentioned, this is supported in the OpenApi specification and I've confirmed that tooling like SwaggerUI works correctly if I manually create a specification where I override specific operations to allow anonymous access using security: []
. I created an IOperationProcessor
in an attempt to override the security based on the presence of the AllowAnonumousAttribute
but as @pfeigl mentions the JSON serialization seems to omit the empty array.
public class ResourceActionSecurityProcessor : IOperationProcessor
{
public ResourceDocsGeneratorSettings Settings { get; }
public ResourceActionSecurityProcessor(ResourceDocsGeneratorSettings settings)
{
Settings = settings;
}
#region IOperationProcessor Members
public bool Process(OperationProcessorContext operationProcessorContext)
{
if (operationProcessorContext is ResourceActionProcessorContext context)
{
if (context.ControllerType.GetCustomAttribute<AllowAnonymousAttribute>() != null || context.MethodInfo.GetCustomAttribute<AllowAnonymousAttribute>() != null)
{
context.ResourceAction.Operation.Operation.Security = new List<OpenApiSecurityRequirement>();
}
}
return true;
}
#endregion
}
The reason why it is important to me to define it on the global level is that API tools like Postman will then add the Authorization on the Collection level instead of the individual operation levels when importing my specification.
The individual operation levels will be set to Inherit auth from parent
as shown below. This implies I can configure the global collection using a single collection variable for the access token and all operations will automatically use the token instead of me having to now manually set the access token on all the operations when importing the collection into Postman.
I've just encountered this issue too and was able to work-around it.
The problem is the OpenApiDocument serialization is using JsonSchema.CreateJsonSerializerContractResolver() which creates a IgnoreEmptyCollectionsContractResolver contract resolver. Instead of trying to resolve the issue with the contract resolver I worked around it by defining the "security" property in the operation extension data.
if (AllowAnonymous(context))
{
if (operation.ExtensionData == null)
{
operation.ExtensionData = new Dictionary<string, object>();
}
operation.ExtensionData["security"] = new Collection<OpenApiSecurityRequirement>();
}
Before going into Details: I'm using WebApi2 with OWIN and scheme set to OpenApi3
With this setup, I'm unable to create a swagger.json which disables the security for given operations (actions).
For this I tried to implement a custom
IOperationProcessor
, which honors theAllowAnonymousAttribute
.On how to disable security for operations, the details can be found here: https://swagger.io/docs/specification/authentication/
There is also a sample about this, technically it just means returning an empty security for this operation:
security: [] # No security
.The actual problem is probably somewhere in the Json serialization. What I would expect:
context.OperationDescription.Operation.Security = null
=> Nosecurity
node at allcontext.OperationDescription.Operation.Security = new List<OpenApiSecurityRequirement>();
=>security
shows up but does not have entries (what I want)What is actually happening: Both situations do not render the
security
node at allI also tried various other combinations, which did not work:
OpenApiSecurityRequirement
results insecurity: [{}]
null
results insecurity: [null]