Securing .NET Microservices on AWS with Microsoft Entra ID
By Braincuber Team
Published on February 11, 2026
In enterprise environments, modernizing legacy .NET applications often means moving to a microservices architecture on AWS. But with distributed services comes the challenge of identity. How do you ensure your Transaction Processor only talks to the Fraud Detector, and that no malicious actor can intercept that request?
The answer lies in OAuth 2.0 Client Credentials flow using Microsoft Entra ID (formerly Azure AD). This allows your services to authenticating "machine-to-machine" without user intervention. In this tutorial, we will secure a mock FinTech system, ensuring our .NET 8 microservices verify each other's identity before processing a single byte of data.
Why Entra ID on AWS?
- Unified Identity: Many organizations already sync their on-prem AD to Entra ID. Using it for AWS workloads keeps identity centralized.
- Standardization: It uses standard JWTs (JSON Web Tokens) that any modern framework can validate.
- Security: Secrets are rotated in Entra ID and securely fetched at runtime, never hardcoded.
Step 1: Entra ID App Registration
We need two identities in Azure: one for the caller (TransactionProcessor) and one for the API (FraudDetector).
- Register the API (FraudDetector):
- Go to App registrations > New registration.
- Name:
FinTech-FraudDetector-API. - Go to Expose an API > Add a scope (e.g.,
api://)./Fraud.Scan
- Register the Client (TransactionProcessor):
- Create a new registration named
FinTech-TransactionProcessor. - Go to API permissions > Add a permission > My APIs > Select
FinTech-FraudDetector-API. - Select the
Fraud.Scanpermission and Grant admin consent. - Go to Certificates & secrets and create a new Client Secret. Copy this immediately!
- Create a new registration named
Step 2: Secure Storage with AWS Secrets Manager
Instead of putting the Client Secret in appsettings.json, we store it in AWS Secrets Manager.
aws secretsmanager create-secret \
--name "fintech/transaction-processor/identity" \
--secret-string '{"ClientId":"","ClientSecret":"","TenantId":""}'
Step 3: Implementing the Token Service
In the TransactionProcessor service, we need a helper class to fetch and cache the Entra ID token. Note the 5-minute cache buffer to avoid hitting rate limits.
using System.Text.Json;
public class TokenAcquisitionService
{
private readonly IConfiguration _config;
private readonly HttpClient _http;
private string? _cachedToken;
private DateTime _expiry = DateTime.MinValue;
public TokenAcquisitionService(IConfiguration config, HttpClient http)
{
_config = config;
_http = http;
}
public async Task GetTokenAsync()
{
// 1. Check Cache (with 5 min buffer)
if (!string.IsNullOrEmpty(_cachedToken) && DateTime.UtcNow < _expiry.AddMinutes(-5))
{
return _cachedToken;
}
// 2. Prepare Request
var tenantId = _config["AzureAd:TenantId"];
var tokenUrl = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token";
var request = new FormUrlEncodedContent(new[]
{
new KeyValuePair("client_id", _config["AzureAd:ClientId"]),
new KeyValuePair("client_secret", _config["AzureAd:ClientSecret"]),
new KeyValuePair("scope", _config["FraudDetector:Scope"]),
new KeyValuePair("grant_type", "client_credentials")
});
// 3. Execute
var response = await _http.PostAsync(tokenUrl, request);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
var data = JsonSerializer.Deserialize(json);
_cachedToken = data.GetProperty("access_token").GetString();
_expiry = DateTime.UtcNow.AddSeconds(data.GetProperty("expires_in").GetInt32());
return _cachedToken!;
}
}
Step 4: Securing the API
Finally, in the FraudDetector service, we configure the authentication middleware to validate the incoming JWT signatures against Entra ID's keys.
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
var builder = WebApplication.CreateBuilder(args);
// Add Microsoft Identity Web (simplifies Entra ID auth)
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddControllers();
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
And secure your controller endpoints:
[Authorize]
[ApiController]
[Route("[controller]")]
public class FraudController : ControllerBase
{
[HttpPost("analyze")]
public IActionResult AnalyzeTransaction([FromBody] Transaction t)
{
// Only accessible with a valid Bearer token
return Ok(new { RiskScore = 0.05, Status = "Approved" });
}
}
Conclusion
You have now established a zero-trust network within your AWS cloud. Even if a malicious actor gains access to your VPC, they cannot invoke the FraudDetector API without a signed JWT from your specific Entra ID tenant. This architecture is the backbone of secure, enterprise-grade distributed systems.
Enterprise Cloud Security?
Microservices are powerful, but complexity breeds risk. Our DevSecOps team can help you audit and harden your AWS infrastructure.
