JWT Swagger authorization using OperationFilter in .NET Core
In this post, we will see how to add JWT bearer authorization to swagger API documentation using OperationFilter.
This technique is very useful if you have schemes that only apply to specific operations. This technique could also be very helpful if you need to apply multiple security schemes.
If looking for .NET 6 or .NET 3.1 solution, please refer
ASP.NET Core 3.1 or .NET 6- JWT Authorize Token in Swagger using IOperationFilter
Today in this article, we will cover below aspects,
We already looked at how to Enable JWT bearer swagger authorization in .NET Core technique where a security scheme was applied globally.
Advantages of swagger specification in a nutshell,
- These specifications are an attempt to create a universal description for REST API.
- Swagger or OpenAPI describes standards and specifications for RESTFul API description.
- This specification provides the advantage of understanding the RESTFul services easily (especially if developers are consuming any new Web API ) plus helps provide easy ready documentation and details of capabilities an organization owns.
In our last post-JWT (JSON Web Token) Authentication in .NET Core, we learned about how to use JWT bearer token for securing .NET Core API.
Open API specification or Swagger 3.0 lets you define the different authentication types for an API like Basic authentication, OAuth, JWT bearer, etc.
ASP.NET Core 3.1 and above please refer to below article,
ASP.NET Core 3.1 and below
Adding swagger documentation in .NET Core
Create a .NET Core 2.2 WebAPI service
Please add below Swashbuckle NuGet package to your WebAPI using the command prompt or package manager console.
Install-Package Swashbuckle.AspNetCore
OR
This single NuGet package shall add all other required components as shown below and you need not have to add them explicitly,
- Swagger
- SwaggerUI
- SwaggerGen
Update ConfigureServices() method
Add the below line to ConfigureServices() method as shown below.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddSwaggerGen(
{
c.SwaggerDoc("v1", new Info { Title = "MyTestService", Version = "v1" });
});
}
Update Configure() method
Add below line to Configure() method as shown below.
app.UseSwagger();
app.UseSwaggerUI(
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "TestService");
});
The generated swagger documentation will be look like as below.
Add JWT Authorization to WebAPI using OperationFilter
Operation filters can be implemented using the IOperationFilter interface.
We can retrieve API descriptions for relevant information like attributes, route information, etc. using this interface. This Interface also lets you define and apply schemes to specific operations.
IOperationFilter Interface
Create a class AuthOperationAttribute derived from IOperationFilter.
Please override the method Apply (..). The following is the final implementation of class AuthOperationAttribute
public class AuthOperationAttribute : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
var authAttributes = context.MethodInfo
.GetCustomAttributes(true)
.OfType<AuthorizeAttribute>()
.Distinct();
if (authAttributes.Any())
{
if (operation.Parameters == null)
operation.Parameters = new List<IParameter>();
operation.Parameters.Add(new NonBodyParameter
{
Name = "Authorization",
In = "header",
Description = "JWT access token",
Required = true,
Type = "string"
});
operation.Responses.Add("401", new Response { Description = "Unauthorized" });
operation.Responses.Add("403", new Response { Description = "Forbidden" });
operation.Security = new List<IDictionary<string, IEnumerable<string>>>();
//Add JWT bearer type
operation.Security.Add(new Dictionary<string, IEnumerable<string>>
{
{ "Bearer", new string[] { } }
});
}
}
}
Please note above parameters list should be as below,
Name = “Authorization” – This is needed for as per JWT header specification
Required = true – This is needed if API needs to executed with authorization only.
Note: Please note that Class Operation is renamed to OpenApiOperation in swagger OpenAPI v3.0. Please see here for more details
Enable OperationFilter in the Swagger Pipeline
OperationFilter in the Swagger Pipeline can be enabled by the below code.
c.OperationFilter< AuthOperationAttribute >();
Update ConfigureServices()
The following is the updated implementation of ConfigureServices().
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddSwaggerGen(
{
c.SwaggerDoc("v1", new Info { Title = "MyTestService", Version = "v1" });
c.OperationFilter<AuthOperationAttribute>();
});
}
Our WebAPI has GET method as secured with [Authorize] attribute as below.
Let’s execute the swagger route for JWT and check the documentation generated for the required API.
So we are able to add the Authorization header as an additional parameter to a method.
So far so good !!
Let’s execute the API using an actual valid JWT bearer token.
The operation gives us a successful response !!
If interested, you can generate a valid JWT-secured token programmatically by following the below article,
If you are looking to understand further IOperationFilter and IDocumentFilter to customize Swagger API documentation pro-grammatically, I would recommend you to refer to the below articles,
Summary
In this post, we learned how to add JWT bearer authorization to swagger documentation using OperationFilter. In .NET Core, it is simple to enable an authentication scheme to secure the API. Open API or Swagger 3.0 specification lets you define the different authentication schemes like BasicAuthScheme, ApiKeyScheme, and OAuth2Scheme.
Please bookmark this page and share it with your friends. Please Subscribe to the blog to receive notifications on freshly published(2024) best practices and guidelines for software design and development.
Do you have any information about how to migrate this to .NET Core 3? The new Swagger implementation changed Operation.Security (now OpenApiOperation) to be of type IList (OpenApiSecurityRequirement being a Dictionary<OpenApiSecurityScheme, IList> now) . The dictionary doesn’t take a simple string as a key, do you know how would one go about this now?
Hi Benjamin -Thanks for your query. Please see .NET Core 3.0 article as below.
https://thecodebuzz.com/jwt-authorization-token-swagger-open-api-asp-net-core-3-0/
There are few breaking changes to be noted as you migrate to 3.0
Can we configure different token for each api in .net core 3.0? Because it looks like parameter from the filter above is ignored there. And configuration with AddSecurityDefinition and AddSecurityRequirement is global for all the APIs.
Hello Victor, yes the above article is meant for global swagger authentication. I shall soon put an article for Operation specific authentication.
Hello Victor- Please see article on implementing Oauth2 authentication in swagger using IOperationFilter: ASP.NET Core- JWT Authorize Token in Swagger using IOperationFilter
As you pointed out there is a design change in how we deal headers using OperationFilter in swagger.
Hope this helps.
This was very helpful. Thank you!
Thanks Ethan. Appreciate your comments and feedback!