Beveiligde API's implementeren achter gateways

Implementeer ASP.NET Core web-API's die zijn beveiligd met Microsoft. Identity.Web achter Azure API-gateways en omgekeerde proxy's, waaronder Azure API Management (APIM), Azure Front Door en Azure Application Gateway.

Begrijp de gatewayvereisten

Wanneer u beveiligde API's achter gateways implementeert, moet u verschillende problemen afhandelen:

  • Doorgestuurde headers : oorspronkelijke aanvraagcontext behouden (schema, host, IP)
  • Tokenvalidatie : ervoor zorgen dat doelgroepclaims overeenkomen met gateway-URL's
  • CORS-configuratie : cross-origin-aanvragen correct verwerken
  • Gezondheidseindpunten - Niet-geauthenticeerde gezondheidscontroles opgeven
  • Routering op basis van pad - Ondersteuning voor padvoorvoegsels op gatewayniveau
  • SSL/TLS-beëindiging - HTTPS correct verwerken wanneer de gateway SSL beëindigt

Veelvoorkomende gatewayscenario's bekijken

Kies een gateway op basis van uw vereisten. In de volgende secties worden de meest voorkomende Azure gatewayservices voor beveiligde API's beschreven.

Azure API Management (APIM)

Use case: Enterprise API-gateway met beleid, snelheidsbeperking, transformatie

Architectuur:

Client → Microsoft Entra ID → Token
Client → APIM (apim.azure-api.net) → Backend API (app.azurewebsites.net)

Belangrijke overwegingen:

  • APIM-beleidsregels kunnen JWT-tokens valideren voordat ze naar de back-end worden doorgestuurd
  • De back-end-API valideert nog steeds tokens
  • De doelgroepclaim moet overeenkomen met de APIM-URL of back-end-URL (dienovereenkomstig configureren)

Azure Front Door

Use case: Wereldwijde taakverdeling, CDN, DDoS-beveiliging

Architectuur:

Client → Microsoft Entra ID → Token
Client → Front Door (azurefd.net) → Backend API (regional endpoints)

Belangrijke overwegingen:

  • Front Door stuurt aanvragen door met X-Forwarded-* headers
  • SSL/TLS-beëindiging bij Front Door
  • Validatie van tokendoelgroep vereist configuratie

Azure Application Gateway

Use case: Regionale taakverdeling, WAF, routering op basis van pad

Architectuur:

Client → Microsoft Entra ID → Token
Client → Application Gateway → Backend API (multiple instances)

Belangrijke overwegingen:

  • WAF-integratie (Web Application Firewall)
  • Routeringsregels op basis van pad
  • Back-endstatustests hebben niet-geverifieerde eindpunten nodig

Algemene patronen configureren

Pas deze configuratiepatronen toe om ervoor te zorgen dat uw beveiligde API correct werkt achter elke gateway.

1. Doorgeschakelde headers middleware

Configureer altijd doorgestuurde headers middleware wanneer u zich achter een gateway bevindt. De volgende code registreert de middleware en stelt deze in voordat verificatie wordt uitgevoerd:

using Microsoft.AspNetCore.HttpOverrides;

var builder = WebApplication.CreateBuilder(args);

// Configure forwarded headers BEFORE authentication
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
                                ForwardedHeaders.XForwardedProto |
                                ForwardedHeaders.XForwardedHost;

    // Clear known networks/proxies to accept forwarded headers from any source
    // (Azure infrastructure will be the proxy)
    options.KnownNetworks.Clear();
    options.KnownProxies.Clear();

    // Limit to specific headers if needed
    options.ForwardedForHeaderName = "X-Forwarded-For";
    options.ForwardedProtoHeaderName = "X-Forwarded-Proto";
    options.ForwardedHostHeaderName = "X-Forwarded-Host";
});

// Add authentication
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));

var app = builder.Build();

// USE forwarded headers BEFORE authentication middleware
app.UseForwardedHeaders();
app.UseAuthentication();
app.UseAuthorization();

app.Run();

De middleware voor doorgestuurde headers is essentieel omdat dit het volgende doet:

  • Behoudt het oorspronkelijke IP-adres van de client voor logboekregistratie
  • HttpContext.Request.Scheme Zorgt ervoor dat het oorspronkelijke HTTPS-schema wordt weerspiegeld
  • Biedt de juiste Host header voor omleidings-URL's en tokenvalidatie

2. Configuratie van token-doelgroep

Optie A: Zowel gateway- als back-end-URL's accepteren

Voeg meerdere geldige doelgroepen toe in uw appsettings.json configuratie:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "your-tenant-id",
    "ClientId": "your-client-id",
    "Audience": "api://your-client-id",
    "TokenValidationParameters": {
      "ValidAudiences": [
        "api://your-client-id",
        "https://your-backend.azurewebsites.net",
        "https://your-apim.azure-api.net"
      ]
    }
  }
}

U kunt ook meerdere doelgroepen programmatisch configureren in Program.cs:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddInMemoryTokenCaches();

// Customize token validation to accept multiple audiences
builder.Services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
{
    var existingValidation = options.TokenValidationParameters.AudienceValidator;

    options.TokenValidationParameters.AudienceValidator = (audiences, token, parameters) =>
    {
        var validAudiences = new[]
        {
            "api://your-client-id",
            "https://your-backend.azurewebsites.net",
            "https://your-apim.azure-api.net",
            builder.Configuration["AzureAd:ClientId"] // Also accept ClientId
        };

        return audiences.Any(a => validAudiences.Contains(a, StringComparer.OrdinalIgnoreCase));
    };
});

Optie B: Doelgroep herschrijven in APIM-beleid

Configureer APIM om de doelgroepclaim te valideren voordat u doorstuurt naar de back-end:

<policies>
    <inbound>
        <validate-jwt header-name="Authorization" failed-validation-httpcode="401">
            <openid-config url="https://login.microsoftonline.com/{tenant-id}/v2.0/.well-known/openid-configuration" />
            <audiences>
                <audience>api://your-client-id</audience>
            </audiences>
        </validate-jwt>

        <!-- Optionally modify token claims for backend -->
        <set-header name="X-Gateway-Validated" exists-action="override">
            <value>true</value>
        </set-header>
    </inbound>
</policies>

3. Gezondheidseindpuntconfiguratie

Gateways vereisen niet-geverifieerde gezondheidseindpunten voor probes. Voeg een gezondheidseindpunt toe vóór de verificatie-middleware om tokenvalidatie te omzeilen.

var app = builder.Build();

// Health endpoint BEFORE authentication middleware
app.MapGet("/health", () => Results.Ok(new { status = "healthy" }))
    .AllowAnonymous();

app.UseForwardedHeaders();
app.UseAuthentication();
app.UseAuthorization();

// Protected endpoints require authentication
app.MapControllers();

app.Run();

U kunt ook het ingebouwde ASP.NET Core Health Checks-framework gebruiken voor uitgebreidere statusrapportage:

using Microsoft.Extensions.Diagnostics.HealthChecks;

builder.Services.AddHealthChecks()
    .AddCheck("api", () => HealthCheckResult.Healthy());

var app = builder.Build();

app.MapHealthChecks("/health").AllowAnonymous();
app.MapHealthChecks("/ready").AllowAnonymous();

app.UseForwardedHeaders();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();

app.Run();

4. CORS-configuratie achter gateways

Wanneer u Azure Front Door of APIM met front-endtoepassingen gebruikt, configureert u CORS om aanvragen van uw gateway-origins toe te staan:

builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowGateway", policy =>
    {
        policy.WithOrigins(
            "https://your-apim.azure-api.net",
            "https://your-frontend.azurefd.net",
            "https://your-app.azurewebsites.net"
        )
        .AllowAnyMethod()
        .AllowAnyHeader()
        .AllowCredentials(); // If using cookies
    });
});

var app = builder.Build();

app.UseForwardedHeaders();
app.UseCors("AllowGateway");
app.UseAuthentication();
app.UseAuthorization();

app.Run();

Belangrijk

CORS moet na de doorgestuurde headers en vóór de verificatie worden geconfigureerd.


Integreren met Azure API Management

Deze sectie bevat de volledige configuratie voor het implementeren van een beveiligde API achter Azure API Management.

De back-end-API configureren

Doorgestuurde headers en Microsoft Entra ID authenticatie instellen in Program.cs:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Identity.Web;

var builder = WebApplication.CreateBuilder(args);

// Forwarded headers for APIM
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.All;
    options.KnownNetworks.Clear();
    options.KnownProxies.Clear();
});

// Authentication
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));

builder.Services.AddControllers();

var app = builder.Build();

// Middleware order matters
app.UseForwardedHeaders();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();

app.Run();

Voeg de Microsoft Entra-configuratie toe aan appsettings.json:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "your-tenant-id",
    "ClientId": "your-backend-api-client-id",
    "Audience": "api://your-backend-api-client-id"
  }
}

Toevoegen van een inkomend APIM-beleid voor JWT-validatie

Definieer een inkomend beleid dat het JWT-token valideert, frequentielimiet toepast en de aanvraag doorstuurt naar de back-end:

<policies>
    <inbound>
        <base />

        <!-- Validate JWT token -->
        <validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized">
            <openid-config url="https://login.microsoftonline.com/{your-tenant-id}/v2.0/.well-known/openid-configuration" />
            <audiences>
                <audience>api://your-backend-api-client-id</audience>
            </audiences>
            <issuers>
                <issuer>https://login.microsoftonline.com/{your-tenant-id}/v2.0</issuer>
            </issuers>
            <required-claims>
                <claim name="scp" match="any">
                    <value>access_as_user</value>
                </claim>
            </required-claims>
        </validate-jwt>

        <!-- Rate limiting -->
        <rate-limit calls="100" renewal-period="60" />

        <!-- Forward original host header -->
        <set-header name="X-Forwarded-Host" exists-action="override">
            <value>@(context.Request.OriginalUrl.Host)</value>
        </set-header>

        <!-- Forward to backend -->
        <set-backend-service base-url="https://your-backend.azurewebsites.net" />
    </inbound>

    <backend>
        <base />
    </backend>

    <outbound>
        <base />
    </outbound>

    <on-error>
        <base />
    </on-error>
</policies>

APIM-API-instellingen configureren

Gebruik de volgende benoemde waarden en API-instellingen om de APIM-configuratie te voltooien:

Benoemde waarden (voor herbruikbaarheid):

  • tenant-id: uw Microsoft Entra-tenant-ID
  • backend-api-client-id: Client-id van de back-end-API
  • backend-base-url: https://your-backend.azurewebsites.net

API-instellingen:

  • API-URL-achtervoegsel: /api (optioneel padvoorvoegsel)
  • Webservice-URL: Instellen via beleid met behulp van benoemde waarden
  • Abonnement vereist: Ja (voegt een andere beveiligingslaag toe)

De clienttoepassing configureren

Client-apps vragen tokens aan voor de back-end-API, niet APIM. Met de volgende code wordt een token verkregen en wordt de API aangeroepen via het APIM-eindpunt:

// Client app requests token
var result = await app.AcquireTokenSilent(
    scopes: new[] { "api://your-backend-api-client-id/access_as_user" },
    account)
    .ExecuteAsync();

// Call APIM URL with token
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", result.AccessToken);

// Add APIM subscription key
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "your-subscription-key");

var response = await client.GetAsync("https://your-apim.azure-api.net/api/weatherforecast");

Integreren met Azure Front Door

Configureer uw beveiligde API voor wereldwijde distributie achter Azure Front Door.

De back-end-API configureren

Doorgestuurde headers instellen voor Azure Front Door in Program.cs:

using Microsoft.AspNetCore.HttpOverrides;

var builder = WebApplication.CreateBuilder(args);

// Configure for Azure Front Door
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
                                ForwardedHeaders.XForwardedProto |
                                ForwardedHeaders.XForwardedHost;

    // Accept headers from any source (Azure Front Door)
    options.KnownNetworks.Clear();
    options.KnownProxies.Clear();

    // Front Door specific headers
    options.ForwardedForHeaderName = "X-Forwarded-For";
    options.ForwardedProtoHeaderName = "X-Forwarded-Proto";
});

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));

var app = builder.Build();

app.UseForwardedHeaders();
app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();

Front Door-origins configureren

Voer de volgende stappen uit in de Azure-portal om de Front Door-oorsprong in te stellen:

  1. Front Door-profiel maken
  2. Voeg een originegroep toe met uw back-end API-exemplaren
  3. Statustests configureren voor /health eindpunt
  4. Alleen HTTPS doorsturen instellen
  5. WAF-beleid inschakelen (optioneel)

Statustestinstellingen:

  • Pad: /health
  • Protocol: HTTPS
  • Methode : GET
  • Interval: 30 seconden

Omgaan met meerdere regio's

Wanneer u implementeert in meerdere regio's achter Front Door, voegt u regiobewustzijn toe voor logboekregistratie en diagnostische gegevens:

// Add region awareness for logging/diagnostics
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

app.Use(async (context, next) =>
{
    // Log the actual client IP and region
    var clientIp = context.Connection.RemoteIpAddress?.ToString();
    var forwardedFor = context.Request.Headers["X-Forwarded-For"].ToString();
    var frontDoorId = context.Request.Headers["X-Azure-FDID"].ToString();

    // Add to logger scope or response headers
    context.Response.Headers.Add("X-Served-By-Region",
        builder.Configuration["Region"] ?? "unknown");

    await next();
});

Tokens valideren met Front Door

Als clients tokens aanvragen die zijn gericht op de Front Door-URL, voegt u deze toe aan de geldige lijst met doelgroepen:

builder.Services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
{
    options.TokenValidationParameters.ValidAudiences = new[]
    {
        "api://your-backend-api-client-id",
        "https://your-frontend.azurefd.net", // Front Door URL
        builder.Configuration["AzureAd:ClientId"]
    };
});

Integreren met Azure Application Gateway

Configureer uw beveiligde API achter Azure Application Gateway met ondersteuning voor Web Application Firewall (WAF).

De back-end-API configureren

Doorgestuurde headers instellen voor Application Gateway in Program.cs:

using Microsoft.AspNetCore.HttpOverrides;

var builder = WebApplication.CreateBuilder(args);

// Application Gateway uses standard forwarded headers
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
                                ForwardedHeaders.XForwardedProto;
    options.KnownNetworks.Clear();
    options.KnownProxies.Clear();
});

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));

builder.Services.AddHealthChecks();

var app = builder.Build();

// Health endpoint for Application Gateway probes
app.MapHealthChecks("/health").AllowAnonymous();

app.UseForwardedHeaders();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();

app.Run();

Instellingen voor Application Gateway configureren

Stel de volgende back-end-, statustest- en WAF-instellingen in de Azure-portal in:

Backendinstellingen:

  • Protocol: HTTPS (aanbevolen) of HTTP
  • Poort: 443 of 80
  • Back-end-pad overschrijven: Nee (tenzij nodig)
  • Aangepaste probe: Ja, wijst naar /health

Gezondheidstest:

  • Protocol: HTTPS of HTTP
  • Host: houd de standaardinstelling aan of specificeer
  • Pad: /health
  • Interval: 30 seconden
  • Ongezonde drempelwaarde: 3

WAF-beleid:

  • WAF met OWASP 3.2-regelset inschakelen
  • Belangrijk: Zorg ervoor dat JWT-tokens in Authorization headers niet worden geblokkeerd
  • Mogelijk moet u WAF-uitsluitingen maken voor RequestHeaderNames die 'Autorisatie' bevat.

Routering op basis van pad instellen

Wanneer u padgebaseerde routeringsregels gebruikt, configureert u de back-end-API om het padvoorvoegsel te verwerken:

// Backend API should work regardless of path prefix
var app = builder.Build();

// Option 1: Use path base (if gateway adds prefix)
app.UsePathBase("/api/v1");

// Option 2: Configure routing explicitly
app.UseForwardedHeaders();
app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();

Toepassingsgatewayregel:

  • Pad: /api/v1/*
  • Backenddoel: uw backendpool
  • Backendinstellingen: Gebruik geconfigureerde instellingen

Veelvoorkomende problemen oplossen

Gebruik deze oplossingen om de meest voorkomende problemen bij het implementeren van beveiligde API's achter gateways op te lossen.

Probleem: 401 Ongeautoriseerd na implementatie achter een gateway

Symptomen:

  • API werkt lokaal, maar retourneert 401 achter de gateway
  • Token lijkt geldig wanneer het is gedecodeerd op jwt.ms

Mogelijke oorzaken:

  1. Doelgroepclaim komt niet overeen

    # Check token audience
    # Decode token and verify 'aud' claim matches one of:
    # - api://your-client-id
    # - https://your-backend.azurewebsites.net
    # - https://your-gateway-url
    
  2. Ontbrekende middleware voor doorgestuurde headers

    // Ensure this is BEFORE authentication
    app.UseForwardedHeaders();
    app.UseAuthentication();
    
  3. Problemen met HTTPS-omleiding

    // If gateway terminates SSL, may need to disable or configure carefully
    if (!app.Environment.IsDevelopment())
    {
        app.UseHttpsRedirection();
    }
    

Solution:

  • Logboekregistratie voor foutopsporing inschakelen om details van tokenvalidatie weer te geven
  • Meerdere geldige doelgroepen toevoegen in tokenvalidatie
  • Controleer of X-Forwarded-* headers door de gateway worden doorgestuurd.

Probleem: Gezondheidstesten mislukken

Symptomen:

  • Gateway markeert de back-end als beschadigd
  • Gezondheidseindpunt retourneert 401

Solution:

Zorg ervoor dat het statuseindpunt wordt uitgevoerd vóór verificatie-middleware:

// Ensure health endpoint is BEFORE authentication
app.MapHealthChecks("/health").AllowAnonymous();

// Alternative: Use custom middleware
app.Map("/health", healthApp =>
{
    healthApp.Run(async context =>
    {
        context.Response.StatusCode = 200;
        await context.Response.WriteAsync("healthy");
    });
});

app.UseAuthentication(); // Health endpoint bypasses this

Probleem: CORS-fouten achter Front Door

Symptomen:

  • Preflight-OPTIES-aanvragen mislukken
  • In de browserconsole worden CORS-fouten weergegeven

Solution:

Voeg uw Front Door en front-end bronnen toe aan het CORS-beleid.

builder.Services.AddCors(options =>
{
    options.AddDefaultPolicy(policy =>
    {
        policy.WithOrigins(
            "https://your-frontend.azurefd.net",
            "https://your-app.com"
        )
        .AllowAnyMethod()
        .AllowAnyHeader()
        .AllowCredentials();
    });
});

var app = builder.Build();

app.UseForwardedHeaders();
app.UseCors(); // Before authentication
app.UseAuthentication();
app.UseAuthorization();

Probleem: Waarschuwingen voor doorgestuurde headers in logboeken

Symptomen:

Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersMiddleware: Unknown proxy

Solution:

Verwijder de bekende netwerken en proxies om doorgestuurde headers van de Azure-infrastructuur te accepteren.

builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    // Clear known networks to accept from any proxy
    options.KnownNetworks.Clear();
    options.KnownProxies.Clear();

    // Or explicitly add Azure IP ranges (more secure but complex)
    // options.KnownProxies.Add(IPAddress.Parse("20.x.x.x"));
});

Probleem: APIM retourneert 401, maar back-end retourneert 200

Symptomen:

  • Het token is geldig voor de back-end.
  • APIM-beleid validate-jwt mislukt

Solution:

Controleer of de APIM-beleidsdoelgroep overeenkomt met de tokendoelgroep:

<validate-jwt header-name="Authorization">
    <openid-config url="https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration" />
    <audiences>
        <!-- Must match the 'aud' claim in your token -->
        <audience>api://your-backend-api-client-id</audience>
    </audiences>
</validate-jwt>

Probleem: Conflict met meerdere verificatieschema's

Symptomen:

  • Zowel JWT-bearer als andere schema's gebruiken
  • Er is een onjuist schema geselecteerd

Solution:

Geef het verificatieschema expliciet op in de controller:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"))
    .AddScheme<MyCustomOptions, MyCustomHandler>("CustomScheme", options => {});

// In controller, specify scheme explicitly
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class WeatherForecastController : ControllerBase
{
    // ...
}

Best practices volgen

Pas deze procedures toe om een veilige, flexibele API-implementatie achter gateways te bouwen.

1. Diepgaande verdediging

Valideer altijd tokens in de back-end-API, zelfs als de gateway deze valideert:

// Gateway validates token (APIM policy)
// Backend ALSO validates token (Microsoft.Identity.Web)
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));

Gatewayconfiguratie kan worden gewijzigd en tokens kunnen opnieuw worden afgespeeld. Diepgaande verdediging is essentieel voor beveiliging.

2. Beheerde identiteiten gebruiken voor gateway-naar-back-endcommunicatie

Als uw gateway de back-end aanroept met een eigen identiteit, configureert u de back-end om zowel gebruikerstokens als beheerde identiteitstokens te accepteren:

// Backend accepts both user tokens and gateway's managed identity
builder.Services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
{
    options.TokenValidationParameters.ValidAudiences = new[]
    {
        "api://backend-api-client-id", // User tokens
        "https://management.azure.com" // Managed identity tokens (if applicable)
    };
});

Gateway-metrieken bewaken

Houd deze belangrijke metrische gegevens bij om inzicht te behouden in uw gatewayimplementatie:

  • Foutpercentages van 401/403
  • Validatiefouten voor tokens
  • Gezondheidscontrolefouten
  • Doorgestuurde headers (voor foutopsporing)

4. Application Insights gebruiken

Voeg Application Insights-telemetrie toe aan eigenschappen van logboekgatewayspecifieke aanvragen:

builder.Services.AddApplicationInsightsTelemetry();

// Log custom properties
app.Use(async (context, next) =>
{
    var telemetry = context.RequestServices.GetRequiredService<TelemetryClient>();
    telemetry.TrackEvent("ApiRequest", new Dictionary<string, string>
    {
        ["ForwardedFor"] = context.Request.Headers["X-Forwarded-For"],
        ["OriginalHost"] = context.Request.Headers["X-Forwarded-Host"],
        ["Gateway"] = "APIM" // or "FrontDoor", "AppGateway"
    });

    await next();
});

5. Scheid gezondheid van gereed

Gebruik afzonderlijke eindpunten voor liveness (draait de service?) en gereedheid (kan de service verkeer accepteren?) controles.

// Health: Is the service running?
app.MapGet("/health", () => Results.Ok()).AllowAnonymous();

// Ready: Can the service accept traffic?
app.MapHealthChecks("/ready", new HealthCheckOptions
{
    Predicate = check => check.Tags.Contains("ready")
}).AllowAnonymous();

builder.Services.AddHealthChecks()
    .AddCheck("database", () => /* check DB */ , tags: new[] { "ready" })
    .AddCheck("cache", () => /* check cache */ , tags: new[] { "ready" });

6. Documenteer de gatewayconfiguratie

Maak een LEESMIJ- of wikipagina die documenteert:

  • Welke gateway(s) worden gebruikt
  • Verwachtingen van de tokendoelgroep
  • CORS-configuratie
  • Gezondheidsonderzoek eindpunten
  • Configuratie van doorgestuurde headers
  • Procedures voor terugdraaien van noodgevallen

Een volledig voorbeeld bouwen met Azure API Management

Deze sectie bevat een volledig, productieklaar voorbeeld van een ASP.NET Core-API achter Azure API Management met Microsoft Entra ID-verificatie.

Back-end-API (ASP.NET Core)

De volgende Program.cs configureert doorgestuurde headers, Microsoft Entra verificatie, statuscontroles en Application Insights:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Identity.Web;

var builder = WebApplication.CreateBuilder(args);

// Forwarded headers for APIM
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.All;
    options.KnownNetworks.Clear();
    options.KnownProxies.Clear();
});

// Authentication
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddMicrosoftGraph()
    .AddInMemoryTokenCaches();

// Application Insights
builder.Services.AddApplicationInsightsTelemetry();

// Health checks
builder.Services.AddHealthChecks();

builder.Services.AddControllers();

var app = builder.Build();

// Health endpoint (unauthenticated)
app.MapHealthChecks("/health").AllowAnonymous();

// Middleware order is critical
app.UseForwardedHeaders();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();

Voeg de volgende Microsoft Entra- en Application Insights-configuratie toe aan appsettings.json:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "your-tenant-id",
    "ClientId": "backend-api-client-id",
    "Audience": "api://backend-api-client-id"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.Identity.Web": "Debug"
    }
  },
  "ApplicationInsights": {
    "ConnectionString": "your-connection-string"
  }
}

De volgende controller vereist verificatie en logt doorgestuurde headers voor foutopsporing.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Identity.Web.Resource;

[Authorize]
[ApiController]
[Route("[controller]")]
[RequiredScope("access_as_user")]
public class WeatherForecastController : ControllerBase
{
    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet]
    public IActionResult Get()
    {
        // Log forwarded headers for debugging
        var forwardedFor = HttpContext.Request.Headers["X-Forwarded-For"];
        var forwardedHost = HttpContext.Request.Headers["X-Forwarded-Host"];

        _logger.LogInformation(
            "Request from {ForwardedFor} via {ForwardedHost}",
            forwardedFor,
            forwardedHost);

        return Ok(new[] { "Weather", "Forecast", "Data" });
    }
}

APIM-configuratie

Het volgende binnenkomende beleid valideert JWT-tokens, past snelheidsbeperking toe, stuurt headers door en configureert CORS:

<policies>
    <inbound>
        <base />

        <!-- Rate limiting per subscription -->
        <rate-limit-by-key calls="100" renewal-period="60"
                           counter-key="@(context.Subscription.Id)" />

        <!-- Validate JWT -->
        <validate-jwt header-name="Authorization"
                      failed-validation-httpcode="401"
                      failed-validation-error-message="Unauthorized">
            <openid-config url="https://login.microsoftonline.com/{tenant-id}/v2.0/.well-known/openid-configuration" />
            <audiences>
                <audience>api://backend-api-client-id</audience>
            </audiences>
            <issuers>
                <issuer>https://login.microsoftonline.com/{tenant-id}/v2.0</issuer>
            </issuers>
            <required-claims>
                <claim name="scp" match="any">
                    <value>access_as_user</value>
                </claim>
            </required-claims>
        </validate-jwt>

        <!-- Forward headers -->
        <set-header name="X-Forwarded-Host" exists-action="override">
            <value>@(context.Request.OriginalUrl.Host)</value>
        </set-header>
        <set-header name="X-Forwarded-Proto" exists-action="override">
            <value>@(context.Request.OriginalUrl.Scheme)</value>
        </set-header>

        <!-- Backend URL -->
        <set-backend-service base-url="https://your-backend.azurewebsites.net" />
    </inbound>

    <backend>
        <base />
    </backend>

    <outbound>
        <base />

        <!-- Add CORS headers if needed -->
        <cors>
            <allowed-origins>
                <origin>https://your-frontend.com</origin>
            </allowed-origins>
            <allowed-methods>
                <method>GET</method>
                <method>POST</method>
            </allowed-methods>
            <allowed-headers>
                <header>*</header>
            </allowed-headers>
        </cors>
    </outbound>

    <on-error>
        <base />
    </on-error>
</policies>