In modern microservice architectures, it is common to have a dedicated Authentication (Auth) microservice responsible for issuing JWT tokens. Other microservices rely on these tokens to authenticate requests and identify users. In this article, we will learn how to validate a JWT issued by an Auth microservice in another ASP.NET Core Web API, extract CompanyId and UserId from the token, and make it accessible in the service.
Prerequisites
Before we start, ensure you have:
An Auth microservice that issues JWT tokens containing
CompanyIdandUserIdas claims.A microservice where you want to validate the token.
Basic knowledge of ASP.NET Core middleware and JWT tokens.
Step 1: Setting Up JWT in AppSettings
First, we need to define the secret key or signing key used to validate JWT tokens. Add the following section to your appsettings.json:
{
"Jwt": {
"Secret": "YourSuperSecretKeyHere12345" // Must match the Auth service key
}
}
Tip: Use a strong secret key (minimum 32 characters) and store it securely using Azure Key Vault or AWS Secrets Manager in production.
Step 2: Creating Middleware to Validate JWT Tokens
Middleware is the best way to handle cross-cutting concerns like authentication. We will create a middleware that:
Reads the token from the
Authorizationheader.Validates the token signature.
Extracts
CompanyIdandUserIdfrom claims.Stores them in
HttpContext.Itemsfor use in controllers.
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public class TokenValidationMiddleware
{
private readonly RequestDelegate _next;
private readonly IConfiguration _configuration;
public TokenValidationMiddleware(RequestDelegate next, IConfiguration configuration)
{
_next = next;
_configuration = configuration;
}
public async Task InvokeAsync(HttpContext context)
{
if (!context.Request.Headers.ContainsKey("Authorization"))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Authorization header missing");
return;
}
var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
if (string.IsNullOrEmpty(token))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Token missing");
return;
}
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_configuration["Jwt:Secret"]);
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken);
var jwtToken = (JwtSecurityToken)validatedToken;
// Extract claims
var companyId = jwtToken.Claims.FirstOrDefault(x => x.Type == "CompanyId")?.Value;
var userId = jwtToken.Claims.FirstOrDefault(x => x.Type == "UserId")?.Value;
if (string.IsNullOrEmpty(companyId) || string.IsNullOrEmpty(userId))
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Invalid token claims");
return;
}
// Store in HttpContext
context.Items["CompanyId"] = companyId;
context.Items["UserId"] = userId;
await _next(context);
}
catch
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Invalid token");
}
}
}
Step 3: Register Middleware
In Program.cs or Startup.cs (for ASP.NET Core 6+):
app.UseMiddleware<TokenValidationMiddleware>();
Note: Ensure this middleware is added before
UseEndpointsto ensure token validation happens first.
Step 4: Access Claims in Controllers
Once the middleware validates the token and stores claims in HttpContext.Items, you can access them in your controllers:
[ApiController]
[Route("api/[controller]")]
public class OrdersController : ControllerBase
{
[HttpGet("my-orders")]
public IActionResult GetMyOrders()
{
var companyId = HttpContext.Items["CompanyId"]?.ToString();
var userId = HttpContext.Items["UserId"]?.ToString();
if (string.IsNullOrEmpty(companyId) || string.IsNullOrEmpty(userId))
return Unauthorized("Invalid token data");
// Your logic to fetch orders based on companyId and userId
return Ok(new { CompanyId = companyId, UserId = userId, Orders = new string[] { "Order1", "Order2" } });
}
}
Step 5: Optional – Remote Validation via Auth Microservice
If you want to ensure the token hasn’t been revoked, you can call the Auth microservice’s Validate Token endpoint:
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
var response = await client.GetAsync("https://authservice/api/validate-token");
if (!response.IsSuccessStatusCode)
{
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Token invalid according to Auth service");
return;
}
This is slower due to network latency but ensures tokens are actively validated.
Best Practices
Use HTTPS for all microservice communication.
Keep secrets secure using environment variables or secret managers.
Validate both issuer and audience if your system has multiple clients or environments.
Use ClaimsPrincipal instead of
HttpContext.Itemsfor cleaner integration withUser.Claimsin large applications.Cache public keys if using asymmetric signing (RSA) to improve performance.
Conclusion
In microservice architectures, validating JWT tokens from a central Auth service ensures secure communication between services. By using custom middleware, you can:
Validate tokens.
Extract user-specific claims like
CompanyIdandUserId.Make them easily accessible in your controllers.
This approach keeps your microservices secure, decoupled, and scalable.

Join the conversation! Your thoughts help the community grow.