How I Learned to Secure My APIs with RS256 JWT Tokens in C#
- Get link
- X
- Other Apps
A few weeks ago, I was working on a project where we needed secure API authentication. We were using JWT (JSON Web Tokens), and I realized that using RS256 for signing tokens was the best approach. Unlike HS256, which uses a shared secret, RS256 uses asymmetric keys — one private key for signing and a public key for verification. This was perfect for our microservices architecture.
Step 1: Generating an RSA Key Pair
First, we need an RSA key pair:
using var rsa = RSA.Create(2048);
var privateKey = rsa.ExportRSAPrivateKey(); // Keep secret
var publicKey = rsa.ExportRSAPublicKey(); // Can share
I learned that storing keys securely is critical. For production, I’d use something like Azure Key Vault or AWS KMS instead of local files.
Step 2: Generating the JWT Token
Next, I used the private key to sign my token:
var rsa = RSA.Create();
rsa.ImportRSAPrivateKey(Convert.FromBase64String("YOUR_PRIVATE_KEY_BASE64"), out _);
var signingCredentials = new SigningCredentials(
new RsaSecurityKey(rsa),
SecurityAlgorithms.RsaSha256
);
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, "user123"),
new Claim(JwtRegisteredClaimNames.Email, "user@example.com"),
new Claim("role", "admin")
};
var token = new JwtSecurityToken(
issuer: "my-api",
audience: "my-audience",
claims: claims,
expires: DateTime.UtcNow.AddHours(1),
signingCredentials: signingCredentials
);
var tokenString = new JwtSecurityTokenHandler().WriteToken(token);
Console.WriteLine(tokenString);
The moment I ran this, I had a signed JWT token ready to use. The RS256 signature ensured that only someone with the private key could generate valid tokens.
Step 3: Validating the JWT Token
Validation is just as important as generation. I used the public key to verify incoming tokens:
var rsa = RSA.Create();
rsa.ImportRSAPublicKey(Convert.FromBase64String("YOUR_PUBLIC_KEY_BASE64"), out _);
var validationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = "my-api",
ValidateAudience = true,
ValidAudience = "my-audience",
ValidateLifetime = true,
IssuerSigningKey = new RsaSecurityKey(rsa)
};
try
{
var principal = new JwtSecurityTokenHandler().ValidateToken(tokenString, validationParameters, out _);
Console.WriteLine("Token is valid!");
}
catch (Exception ex)
{
Console.WriteLine("Token validation failed: " + ex.Message);
}
This gave me peace of mind that any token without a valid signature would be rejected.
Step 4: Extracting Claims
Once the token is validated, I could access claims like this:
var email = principal.FindFirst(JwtRegisteredClaimNames.Email)?.Value;
var role = principal.FindFirst("role")?.Value;
Console.WriteLine($"Email: {email}, Role: {role}");
It was neat to see how easy it was to get user information directly from the token. This makes authorization in APIs straightforward.
Key Lessons Learned
- RS256 uses asymmetric encryption, which is safer for distributed systems.
- Always keep your private key secret and share only the public key.
- Always validate expiration (`exp`) claims.
- Using JWT claims makes it easy to handle roles and permissions in APIs.
- Libraries like Microsoft.AspNetCore.Authentication.JwtBearer make integrating JWT in ASP.NET Core a breeze.
RS256 JWT tokens gave me strong security and flexibility. After implementing this, I felt much more confident exposing my APIs to clients while keeping them secure.
Tip: For a complete working example, I also created a small ASP.NET Core Web API demo with JWT token generation, validation, and role-based claims. Stay tuned for my next post where I’ll walk you through the code end-to-end.
- Get link
- X
- Other Apps
Comments
Post a Comment