Authentication and Authorization both on REST API and GraphQL API
Using JSON Web Token (JWT) to secure our APIs with authentication and authorization was fully ease to implement in .NET’s ecosystem. The article introduced a way using JWT for protection our end points.
For introducing JWT into .NET environment, simply added code into “Program.cs”:
var builder = WebApplication.CreateBuilder(args);
// .....
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options => options.TokenValidationParameters =
new TokenValidationParameters
{
ValidIssuer = builder.Configuration.GetValue<string>("Jwt:Issuer"),
ValidAudience = builder.Configuration.GetValue<string>("Jwt:Audience"),
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration.GetValue<string>("Jwt:Secret") ??
"SUPER_KEY"))
});
We setup our token parameters from appsettings.json under JWT sections.
And implemented our get token under “Mutation.cs”:
public class Mutation
{
[AllowAnonymous]
public TokenPayload GetToken(string email, [Service] AuthService authService)
{
var token = authService.GenerateAccessToken(email, Guid.NewGuid().ToString(), [RoleConstants.Admin]);
return new TokenPayload(Token: token);
}
}
public class AuthService
{
public string GenerateAccessToken(string email, string userId, string[] roles)
{
// find admin user by email using ef framework..
var adminUser = adminUserService.FindByEmail(email) ?? throw new ApiBusinessException(ErrorCode.Unauthorized, "Unauthorized");
var claims = new List<Claim>
{
new(ClaimTypes.NameIdentifier, email),
new(ClaimTypes.Name, userId)
};
// add role we want to grant
claims = [.. claims, .. roles.Select(role => new Claim(ClaimTypes.Role, role))];
var token = jwtManager.SignTokenWithClaims(claims);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
Test if our get token mutation shall get back token:
Wrote the get identity query under “Qeruy.cs”:
public class Query
{
[Authorize(Roles = [$"{RoleConstants.Admin}"])]
//[Authorize(Roles = ["User"])]
public string? GetMe(ClaimsPrincipal? user)
{
return user?.FindFirstValue(ClaimTypes.NameIdentifier) + ", " + user?.FindFirstValue(ClaimTypes.Role);
}
}
Test query “GetMe” to see if with Bear token that we could retrieve user information back as “Admin”role.
Switch query “GetMe” apply with “User” role only that return authorized failed (403).
Implemented REST API “Welcome” that apply with “Admin” role.
public class XXXController : BaseController
{
[HttpGet]
[Route("welcome")]
[Authorize(Roles = RoleConstants.Admin)]
public IActionResult Welcome()
{
return Ok($"{DateTimeOffset.Now}, Welcome to [Admin] {nameof(XXXController)}!");
}
}
Test invoked with same token that return OK.
Switched “Welcome” apply with “User” role only that return authorized failed (403).
Hot Chocolate framework did a great job of seamless integration JWT authentication and authorization with .NET platform:)