Reputation:
I searched for possible ways to add a request header parameter that would be added automatically to every method in my web-api
but I couldn't find a clear one.
While searching I found that the method OperationFilter()
has something to do with it.
Upvotes: 88
Views: 180193
Reputation: 1027
For me I just wanted to have custom headers to be passed from the Swagger UI.
Thanks to @M.Saeed Palideh for providing the answer.
For this purpose, I have created a filter named SwaggerHeaderParameterFilter
:
Filters/SwaggerHeaderParameterFilter.cs
namespace SwagApi.Filters
{
using System.Collections.Generic;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
public class SwaggerHeaderParameterFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
operation.Parameters ??= new List<OpenApiParameter>();
operation.Parameters.Add(new OpenApiParameter()
{
Name = "Authorization",
In = ParameterLocation.Header,
Required = false
});
operation.Parameters.Add(new OpenApiParameter()
{
Name = "Custom1",
In = ParameterLocation.Header,
Required = false
});
operation.Parameters.Add(new OpenApiParameter()
{
Name = "Custom2",
In = ParameterLocation.Header,
Required = false
});
}
}
}
Startup.cs
namespace SwagApi
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSwaggerGen(o => o.OperationFilter<SwaggerHeaderParameterFilter>());
}
}
}
I don't wanted them to be required, so I made Required
as false.
This appears as shown below:
Upvotes: 3
Reputation: 3246
Another customized implementation for:
Following some of the answers from this thread did get me a required field for Authorization. However I had run into a different problems. I need to have the followings fixed:
Authorization
field.To overcome the above issues I have done the followings:
IOperationFilter
type filter to indicate which API endpoints requires authentication and which ones are anonymous typeHere are the codes:
#Step-1: The custom IOperationFilter
type filrer:
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (context.ApiDescription.ActionDescriptor is ControllerActionDescriptor descriptor)
{
// If [AllowAnonymous] is not applied or [Authorize] or Custom Authorization filter is applied on either the endpoint or the controller
if (!context.ApiDescription.CustomAttributes().Any((a) => a is AllowAnonymousAttribute)
&& (context.ApiDescription.CustomAttributes().Any((a) => a is AuthorizeAttribute)
|| descriptor.ControllerTypeInfo.GetCustomAttribute<AuthorizeAttribute>() != null))
{
if (operation.Security == null)
operation.Security = new List<OpenApiSecurityRequirement>();
operation.Security.Add(
new OpenApiSecurityRequirement{
{
new OpenApiSecurityScheme
{
Name = "Authorization",
In = ParameterLocation.Header,
BearerFormat = "Bearer token",
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[]{ }
}
});
}
}
}
Then in the startup.cs file, within the ConfigureServices
method add the filter like this:
services.AddSwaggerGen(options =>
{
...
options.OperationFilter<AddRequiredHeaderParameter>();
...
...
}
Doing the above will add an icon to the API endpoints where Authentication is required. Here is the result:
#Step-2: Then we need the Auth token input UI. Add the following code right after the line in the startup.cs where you have added the IOperationFilter
filter:
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
Name = "Authorization",
Type = SecuritySchemeType.Http,
Scheme = "Bearer",
BearerFormat = "JWT",
In = ParameterLocation.Header,
Description = "JWT Authorization header. \r\n\r\n Enter the token in the text input below.,
});
This will get you a Authorize button at the top of the API descriptor page. Clicking the button will bring a popup window where you can input the Auth token and have it passed down with each API call.
Upvotes: 5
Reputation: 4431
Not sure if it was answered with the 2021 Sep release for .net 5.0 but I took Rami'es answer and adapted it to the following:
namespace PartnerLicense
{
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using Walter.Web.FireWall.Reseller;
public class AddRequiredHeaderParameter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
operation.Parameters.Add(new()
{
Description = "Add your reseller ID here",
Name = HeaderKeys.ResellerId,
In = ParameterLocation.Header,
Required = true
});
}
}
}
Upvotes: 0
Reputation: 1839
What the user "G T" wrote is correct but it is not working with Swagger 5. We have some new changes:
From: Operation
to: OpenApiOperation
From: IParameter
to: OpenApiParameter
From: NonBodyParameter
to: OpenApiParameter
, and the most important is...
From: Type = "string"
to: Schema = new OpenApiSchema { Type = "String" }
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace MyAPI
{
public class AuthorizationHeaderParameterOperationFilter: IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors;
var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);
if (isAuthorized && !allowAnonymous)
{
if (operation.Parameters == null)
operation.Parameters = new List<OpenApiParameter>();
operation.Parameters.Add(new OpenApiParameter
{
Name = "Authorization",
In = ParameterLocation.Header,
Description = "access token",
Required = true,
Schema = new OpenApiSchema
{
Type = "string",
Default = new OpenApiString("Bearer ")
}
});
}
}
}
}
And in Startup => ConfigureServices => services.AddSwaggerGen()
c.OperationFilter<AuthorizationHeaderParameterOperationFilter>();
Upvotes: 143
Reputation: 191
In my case (.NET 5) I have to change some :
using System.Collections.Generic;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
public class AddRequiredHeaderParameter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.Parameters == null)
operation.Parameters = new List<OpenApiParameter>();
operation.Parameters.Add(new OpenApiParameter()
{
Name = "userNr",
In = ParameterLocation.Header,
Required = true
});
operation.Parameters.Add(new OpenApiParameter()
{
Name = "periodNo",
In = ParameterLocation.Header,
Required = true
});
}
}
and in Startup.cs --> ConfigureServices --> AddSwaggerGen
add
c.OperationFilter<AddRequiredHeaderParameter>();
Upvotes: 13
Reputation: 89
This works for Swashbucke.AspNetCore 5.6.3
Create a new file and add the code below to the file
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace YourNameSpace
{
public class AuthorizationHeaderParameterOperationFilter:IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.Security == null)
operation.Security = new List<OpenApiSecurityRequirement>();
var scheme = new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "bearer" } };
operation.Security.Add(new OpenApiSecurityRequirement
{
[scheme] = new List<string>()
});
}
}
}
In your Startup.cs add the code below to the ConfigureServices under services.AddSwaggerGen()
c.AddSecurityDefinition("bearer", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
BearerFormat = "JWT",
In = ParameterLocation.Header,
Scheme = "bearer"
});
c.OperationFilter<AuthorizationHeaderParameterOperationFilter>();
All should work fine now for more information check here
Upvotes: 3
Reputation: 1033
If swagger is used in ASP.Net MVC5, and required to add headers to get input from swagger UI.
Create a class inherited from IOperationFilter
:
using Swashbuckle.Swagger;
using System.Collections.Generic;
using System.Web.Http.Description;
public class AddHeaderParameters : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
if (operation.parameters == null)
operation.parameters = new List<Parameter>();
operation.parameters.Add(new Parameter
{
name = "AccountUserName",
@in = "header",
type = "string",
required = true,
//description = "Account username"
});
}
}
Give reference of this class in SwaggerConfig.cs
inside Configuration.EnableSwagger
as:
c.OperationFilter<AddHeaderParameters>();
Important thing to note that the header name supposed to match with the actual header you have created for API.
Upvotes: 4
Reputation: 401
I have improved the respectful Wille Esteche's answer a bit. If you want to apply headers not to all methods, but only to your selected controller methods, you can use attributes.
[HttpPost]
[Route(nameof(Auth))]
[SwaggerHeader(Constants.HeaderDomainSid, "Encrypted User.Sid got from client", "abc123", true)]
public ActionResult<string> Auth([FromHeader(Name = Constants.HeaderDomainSid)] string headerDomainSid = null)
{ .....
Attribute class:
public class SwaggerHeaderAttribute : Attribute
{
public string HeaderName { get; }
public string Description { get; }
public string DefaultValue { get; }
public bool IsRequired { get; }
public SwaggerHeaderAttribute(string headerName, string description = null, string defaultValue = null, bool isRequired = false)
{
HeaderName = headerName;
Description = description;
DefaultValue = defaultValue;
IsRequired = isRequired;
}
}
Filter:
public class SwaggerHeaderFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
operation.Parameters ??= new List<OpenApiParameter>();
if (context.MethodInfo.GetCustomAttribute(typeof(SwaggerHeaderAttribute)) is SwaggerHeaderAttribute attribute)
{
var existingParam = operation.Parameters.FirstOrDefault(p =>
p.In == ParameterLocation.Header && p.Name == attribute.HeaderName);
if (existingParam != null) // remove description from [FromHeader] argument attribute
{
operation.Parameters.Remove(existingParam);
}
operation.Parameters.Add(new OpenApiParameter
{
Name = attribute.HeaderName,
In = ParameterLocation.Header,
Description = attribute.Description,
Required = attribute.IsRequired,
Schema = string.IsNullOrEmpty(attribute.DefaultValue)
? null
: new OpenApiSchema
{
Type = "String",
Default = new OpenApiString(attribute.DefaultValue)
}
});
}
}
}
Upvotes: 26
Reputation: 5943
Yes you can do it via inheriting from IOperationFilter
You can find the answer on GitHub here: AddRequiredHeaderParameter
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
public class AddRequiredHeaderParameter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
if (operation.Parameters == null)
operation.Parameters = new List<IParameter>();
operation.Parameters.Add(new NonBodyParameter
{
Name = "X-User-Token",
In = "header",
Type = "string",
Required = false
});
}
}
Then you go to your SwaggerConfig.cs
file and add the following in the AddSwaggerGen
section:
c.OperationFilter<AddRequiredHeaderParameter>();
Rebuild, and enjoy.
Upvotes: 91
Reputation: 109
For Asp .Net MVC 5 you can use.
Following the need to be done in Swagger Config file.
private class AddAuthorizationHeaderParameter: IOperationFilter // as a nested class in script config file.
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
if (operation.parameters == null)
operation.parameters = new List<Parameter>();
operation.parameters.Add(new Parameter
{
name = "Authorization",
@in = "header",
type = "string",
required = true
});
}
}
c.OperationFilter<AddAuthorizationHeaderParameter>(); // finally add this line in .EnableSwagger
You can also add any no of headers for header implementation in Swagger.
Upvotes: 7
Reputation: 3783
Another way to add custom headers is by adding parameters into controller action.
The following example will add x-test
parameter to the UI:
[HttpPost]
public IActionResult Test([FromHeader(Name="x-test")][Required] string requiredHeader)
{
return Ok();
}
Upvotes: 67
Reputation: 633
Also you may have a base model class and use attribute [FromHeader] for properties which should be sent in custom headers. Something like this:
public class AuthenticatedRequest
{
[FromHeader(Name = "User-Identity")]
public string UserIdentity { get; set; }
}
At least it works fine for ASP.NET Core 2.1 and Swashbuckle.AspNetCore 2.5.0.
Upvotes: 2