visit
FBI Agents with Clearance Level 1 will be able to access public files, and agents with Clearance Level 2 will be able to access pubic and classified files.
But before we get started, here's some theory.In the above scenario, providing documents is like logging in – where once verified, the agent will be provided with a token (badge). This process is called Authentication. It determines whether agents are who they claim to be.
We are going to use JSON Web Tokens (JWT) Bearer tokens for authentication. Bearer tokens are a type of token that's generated by servers, and which contain details of the claims/roles of a user trying to login. Bearer tokens are mostly structured tokens like JWT. You can if you want to learn more.
This is because FBI Agent is not authorised to access classified files. Authorisation determines what agents can and cannot access.
As mentioned above, the JWT Bearer token contains claims/roles. Based on it, our server decides whether to give access to a private resource or not.Create a new project by executing the command dotnet new webapi --name FBI from your CLI. It will create a project with a sample WeatherForecast API.
Why work on WeatherForecast when we can work on FBI? Go ahead and delete the WeatherForecast.cs file.Add the necessary dependencies by executing these commands:dotnet add package Microsoft.IdentityModel.Tokens --version 6.9.0
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer --version 5.0.4
var TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = "//fbi-demo.com",
ValidAudience = "//fbi-demo.com",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SXkSqsKyNUyvGbnHs7ke2NCq8zQzNLW7mPmHbnZZ")),
ClockSkew = TimeSpan.Zero // remove delay of token when expire
};
services
.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(cfg =>
{
cfg.TokenValidationParameters = TokenValidationParameters;
});
services.AddAuthorization(cfg =>
{
cfg.AddPolicy("Admin", policy => policy.RequireClaim("type", "Admin"));
cfg.AddPolicy("Agent", policy => policy.RequireClaim("type", "Agent"));
cfg.AddPolicy("ClearanceLevel1", policy => policy.RequireClaim("ClearanceLevel", "1", "2"));
cfg.AddPolicy("ClearanceLevel2", policy => policy.RequireClaim("ClearanceLevel", "2"));
});
A claim is a name value pair that represents what the subject is. Since clearance level 2 can also access clearance level 1, we have put "1", "2" in ClearanceLevel1. You can read more about claims .
Lastly, in the Configure method, add the below line just above app.UseAuthorization();app.UseAuthentication();
using Microsoft.AspNetCore.Mvc;
namespace FBI.Controllers
{
[ApiController]
[Route("[controller]")]
public class AdminController : ControllerBase
{
public AdminController() { }
}
}
[HttpPost]
[Route("[action]")]
public IActionResult Login([FromBody] User User)
{
// TODO: Authenticate Admin with Database
// If not authenticate return 401 Unauthorized
// Else continue with below flow
var Claims = new List<Claim>
{
new Claim("type", "Admin"),
};
var Key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("SXkSqsKyNUyvGbnHs7ke2NCq8zQzNLW7mPmHbnZZ"));
var Token = new JwtSecurityToken(
"//fbi-demo.com",
"//fbi-demo.com",
Claims,
expires: DateTime.Now.AddDays(30.0),
signingCredentials: new SigningCredentials(Key, SecurityAlgorithms.HmacSha256)
);
return new OkObjectResult(new JwtSecurityTokenHandler().WriteToken(Token));
}
[HttpPost]
[Route("[action]")]
[Authorize(Policy = "Admin")]
public IActionResult GenerateBadge([FromBody] Agent Agent)
{
// TODO: Add the agent to the database
return new CreatedResult("Agent/1", Agent);
}
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "FBI", Version = "v1" });
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
In = ParameterLocation.Header,
Description = "Please enter JWT with Bearer into field",
Name = "Authorization",
Type = SecuritySchemeType.ApiKey
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement {
{ new OpenApiSecurityScheme
{
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer"}
},
new string[] {}
}
});
});
When you refresh Swagger in your browser you will notice an Authorize button on the right side above the list of APIs.
Click on the newly added Authorize button in Swagger which will open up a dialog. We need to mention what type of token it is. So first enter Bearer in the field then a space and then the token generated from the /Admin/Login API from the previous section.
Click on the header to lock in the token. Now you are all set. When you execute the GenerateBadge API again you will get a token (analogous to badge). Keep this token handy, since we require it in the next section. Also make sure to pass ClearanceLevel as 1 for now.
using Microsoft.AspNetCore.Mvc;
namespace FBI.Controllers
{
[ApiController]
[Route("[controller]")]
[Authorize(Policy = "Agent")]
public class AgentController : ControllerBase
{
public AgentController() { }
}
}
[HttpGet]
[Route("[action]")]
[Authorize(Policy = "ClearanceLevel1")]
public ActionResult<String> AccessPublicFiles()
{
return new OkObjectResult("Public Files Accessed");
}
[HttpGet]
[Route("[action]")]
[Authorize(Policy = "ClearanceLevel2")]
public ActionResult<String> AccessClassifiedFiles()
{
return new OkObjectResult("Classified Files Accessed");
}
If you try to access these API's with the Admin token you will get 403 Forbidden error. So go ahead and click on the Authorize button again and click on logout. Then, get the token from the above step and paste in the field with Bearer as a prefix.
Now when you access the /Agent/AccessPublicFiles API you will see response 200 with the message Public Files Accessed. But when you try the classified API you get the 403 Forbidden error.
Fast forward 3 years and our Agent's performance has been mind bogglingly good. Management has now decided to promote them to ClearanceLevel2.
The Agent goes to the Admin and asks them to provide a token/badge with Clearance Level 2.
The Admin calls the /Admin/Login API to generate their own token first. They then enter it in the Authorize dialog.
The admin then calls the /Admin/GenerageBadge API with value 2 in the ClearanceLevel. This generates a new token/badge which they then hand over to Agent.
The Agent enters this token/badge in the Authorize dialog and when they now call /Agent/AccessClassifiedFiles they are pleased to see the result Classified Files Accessed.
Previously published at