In this article, we are going to look at how to implement swagger authorization in an ASP.Net Core Web API application.
We are only going to cover how to set up swagger to accept JSON Web Token (JWT) and how to utilize the token generated to access restricted resources in Swagger. That said, if you are not familiar with the JWT authentication, you can check out our articles ASP.NET Core Authentication One and ASP.NET Core Authentication Two for more information.
Additionally, for more information on configuring Swagger, you can visit our article Configuring and Using Swagger UI in ASP.NET Core.
Using the articles mentioned above as a guide, we have prepared a new ASP.NET Web API project and integrated swagger and JWT into it.
Overview of the ASP.NET Core Web API Project
Our app is going to be a straightforward product inventory.
Let’s take a look at the Product
model:
public class Product { public int Id { get; set; } public string? Name { get; set; } }
Next, we can find a ProductStore
class that acts as a mock database:
public static class ProductStore { private static Product[] products = new Product[] { new Product { Id = 1, Name = "Rubber duck"}, new Product { Id = 2, Name = "Flip flop"}, new Product { Id = 3, Name = "Magic Wand"}, new Product { Id = 4, Name = "Glitter pen"} }; public static IEnumerable<Product> GetProducts() { return products; } public static Product? GetProduct(int id) { foreach (var product in products) { if (product.Id == id) return product; } return null; } }
Following that, we have the ProductController
that holds two action methods GetAllProducts
and GetAProduct
:
public class ProductController : ControllerBase { [HttpGet] public IActionResult GetAllProducts() { var products = ProductStore.GetProducts(); return Ok(products); } [HttpGet("{id}")] public IActionResult GetAProduct(int id) { var product = ProductStore.GetProduct(id); if (product is null) return NotFound(); return Ok(product); } }
Finally, we have the AuthController
that contains the Login
action method:
public class AuthController : ControllerBase { [HttpPost, Route("login")] public IActionResult Login(LoginModel model) { if (model == null) { return BadRequest("Invalid client request"); } if (model.UserName == "johndoe" && model.Password == "johndoe2410") { var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("superSecretKey@2410")); var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256); var tokenOptions = new JwtSecurityToken( issuer: "CodeMaze", audience: "https://localhost:5001", claims: new List<Claim>(), expires: DateTime.Now.AddMinutes(5), signingCredentials: signinCredentials ); var tokenString = new JwtSecurityTokenHandler().WriteToken(tokenOptions); return Ok(new { Token = tokenString }); } else { return Unauthorized(); } } }
For the sake of keeping things simple, in the code above we’ve hardcoded the expected login credentials and security key.
Adding the Authorize Attribute to an Action Method
We use the Authorize
attribute when we want to restrict access to an action method and ensure that only authenticated users can access it.
So, let’s decorate our GetAllProducts
action method with the Authorize
attribute:
[HttpGet, Authorize] public IActionResult GetAllProducts() { var products = ProductStore.GetProducts(); return Ok(products); }
After that, we can run the project and log in, and we are going to get a token:
But when we try to access the GetAllProducts
endpoint, we still get a 401 UnAuthorized
error since we need to supply the generated bearer token to swagger to gain access.
So, let’s see how we can configure Swagger to accept bearer tokens and enable authorization with Swagger.
Configuring Authorization with Swagger – Accepting Bearer Token
To set up authorization with Swagger, we have to modify our Program.cs
class, under the Swagger configuration:
builder.Services.AddSwaggerGen(opt => { opt.SwaggerDoc("v1", new OpenApiInfo { Title = "MyAPI", Version = "v1" }); opt.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { In = ParameterLocation.Header, Description = "Please enter token", Name = "Authorization", Type = SecuritySchemeType.Http, BearerFormat = "JWT", Scheme = "bearer" }); opt.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type=ReferenceType.SecurityScheme, Id="Bearer" } }, new string[]{} } }); });
In the code, we added two extra SwaggerGenOptions
. The AddSecurityDefinition
action method tells swagger the type of protection we want for our API. It takes in the name of the security scheme and a security scheme definition. The AddSecurityRequirement
action method adds the global security requirement.
Now when we run our app, we see an authorize button at the right-hand corner of our swagger user interface:
Let’s test this out.
Using Authorization with Swagger to Access Protected Resources
We’ll log in once again to get our bearer token.
After that, we are going to click the Authorize
button, which is going to bring up the authorization modal:
Let’s paste the generated token into the authorization modal’s input field, and then click Authorize
and Close
to dismiss the modal.
Now when we try to access the GetAllProducts
endpoint we get a list of products from the ProductStore
.
Using the generated token, we are able to get the authorization we need to access the protected GetAllProducts
endpoint.
Conclusion
In this article, we have learned about:
- Adding authorize attribute to our endpoint
- How to configure the swagger user interface to accept bearer token
- How to access protected resources by passing JWT to Swagger