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");
}
}
}
Join the conversation! Your thoughts help the community grow.