Apache Kafka Implementation in .NET – A Practical Microservices Guide

Modern enterprise applications demand high throughput, fault tolerance, and real-time data processing . Traditional synchronous APIs struggle at scale. This is where Apache Kafka becomes a backbone for event-driven microservices. In this article, we will explore Kafka implementation using .NET with real-world architecture, producer & consumer examples, and best practices. Why Kafka for Microservices? High-throughput event streaming Loose coupling between services Fault tolerance and durability Replayable event history Horizontal scalability Kafka Architecture – Core Concepts Kafka Components Producer – Publishes events Topic – Logical event stream Partition – Parallelism unit Broker – Kafka server Consumer Group – Scalable consumers Offset – Message position Kafka Microservices Architecture +-------------------+ | Web / API Layer | +-------------------+ | v +-------------------+ | Kafka Produce...

How I Learned to Secure My APIs with RS256 JWT Tokens in C#

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.

Comments

Popular posts from this blog

How I Solved a Real Entity Framework Deadlock Caused by Different Table Order in High-Transaction Systems

How I Built a JWT Refresh Token Middleware in ASP.NET Core

Azure Service Bus vs Apache Kafka in .NET Microservices

A Practical Comparison Guide