Distribuera skyddade API:er bakom gatewayer

Distribuera ASP.NET Core webb-API:er som skyddas med Microsoft.Identity.Web bakom Azure API-gatewayer och omvända proxyservrar, inklusive Azure API Management (APIM), Azure Front Door och Azure Application Gateway.

Förstå kraven för gatewayen

När du distribuerar skyddade API:er bakom gatewayer måste du hantera flera problem:

  • Vidarebefordrade rubriker – Bevara den ursprungliga begärandekontexten (schema, värd, IP)
  • Tokenverifiering – Se till att målgruppsanspråk matchar gateway-URL:er
  • CORS-konfiguration – Hantera begäranden mellan ursprung korrekt
  • Hälsoslutpunkter – Tillhandahålla oautentiserade hälsokontroller
  • Sökvägsbaserad routning – Stöd för sökvägsprefix på gatewaynivå
  • SSL/TLS-avslutning – Hantera HTTPS korrekt när gatewayen avslutar SSL

Genomgå vanliga scenarier med gateways

Välj en gateway baserat på dina krav. I följande avsnitt beskrivs de vanligaste Azure gateway-tjänsterna för skyddade API:er.

Azure API Management (APIM)

Användningsfall: Företags-API-gateway med principer, hastighetsbegränsning, transformering

Arkitektur:

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

Viktiga saker att tänka på:

  • APIM-principer kan verifiera JWT-token innan de vidarebefordras till serverdelen
  • Serverdels-API:et validerar fortfarande token
  • Målgruppsanspråket måste matcha APIM-URL:en eller serverdels-URL:en (konfigurera därefter)

Azure Front Door

Användningsfall: Global belastningsutjämning, CDN, DDoS-skydd

Arkitektur:

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

Viktiga saker att tänka på:

  • Front Door vidarebefordrar begäranden med X-Forwarded-* rubriker
  • SSL/TLS-avslutning vid Front Door
  • Tokenvalidering för målgrupp måste konfigureras

Azure Application Gateway

Användningsfall: Regional belastningsutjämning, WAF, sökvägsbaserad routning

Arkitektur:

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

Viktiga saker att tänka på:

  • Web Application Firewall (WAF)-integrering
  • Sökvägsbaserade routningsregler
  • Serverdelshälsoavsökningar behöver oautentiserade slutpunkter

Konfigurera vanliga mönster

Använd de här konfigurationsmönstren för att säkerställa att ditt skyddade API fungerar korrekt bakom alla gatewayer.

1. Vidarebefordrade HTTP-huvuden mellanvara

Konfigurera alltid vidarebefordrade huvudmellanprogram bakom en gateway. Följande kod registrerar mellanprogrammet och anger att det ska köras före autentisering:

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();

Vidarebefordrade huvudmellanprogram är viktigt eftersom det:

  • Bevarar den ursprungliga klientens IP-adress för loggning
  • Ser till att HttpContext.Request.Scheme det ursprungliga HTTPS-schemat visas
  • Innehåller rätt Host rubrik för omdirigerings-URL:er och tokenverifiering

Konfiguration av token-målgrupp

Alternativ A: Acceptera både gateway- och serverdels-URL:er

Lägg till flera giltiga målgrupper i konfigurationen appsettings.json :

{
  "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"
      ]
    }
  }
}

Du kan också konfigurera flera målgrupper programmatiskt i 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));
    };
});

Alternativ B: Skriv om audience i APIM-policy

Konfigurera APIM för att verifiera målgruppsanspråket innan du vidarebefordrar till serverdelen:

<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. Konfiguration av slutpunkt för hälsotillstånd

Gatewayer kräver oautentiserade hälsoslutpunkter för avsökningar. Mappa en hälsoslutpunkt före mellanprogrammet för autentisering för att kringgå tokenverifiering:

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();

Du kan också använda det inbyggda ASP.NET Core Health Checks-ramverket för rikare hälsorapportering:

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-konfiguration bakom gatewayer

När du använder Azure Front Door eller APIM med frontend-applikationer konfigurerar du CORS för att tillåta begäranden från gateway-ursprung.

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();

Viktigt

CORS måste konfigureras efter vidarebefordrade huvuden och före autentisering.


Integrera med Azure API Management

Det här avsnittet innehåller den fullständiga konfigurationen för att distribuera ett skyddat API bakom Azure API Management.

Konfigurera backend-API:t

Konfigurera vidarebefordrade header-filer och autentiseringen av Microsoft Entra ID i 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();

Lägg till konfigurationen Microsoft Entra i 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"
  }
}

Lägg till en inkommande princip i APIM för JWT-validering

Definiera en inkommande princip som validerar JWT-token, tillämpar hastighetsbegränsning och vidarebefordrar begäran till serverdelen:

<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>

Konfigurera APIM API-inställningar

Använd följande namngivna värden och API-inställningar för att slutföra APIM-konfigurationen:

Namngivna värden (för återanvändning):

  • tenant-id: Ditt Microsoft Entra klient-ID
  • backend-api-client-id: Backend-API:ns klient-ID
  • backend-base-url: https://your-backend.azurewebsites.net

API-inställningar:

  • API URL-suffix: /api (valfritt sökvägsprefix)
  • Webbtjänst-URL: Ställs in via policy med namngivna värden
  • Prenumeration krävs: Ja (lägger till ytterligare ett säkerhetslager)

Konfigurera klientprogrammet

Klientappar begär token för serverdels-API:et, inte APIM. Följande kod hämtar en token och anropar API:et via APIM-slutpunkten:

// 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");

Integrera med Azure Front Door

Konfigurera ditt skyddade API för global distribution bakom Azure Front Door.

Konfigurera serverdels-API:et

Konfigurera vidarebefordrade rubriker för Azure Front Door i 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();

Konfigurera Front Door-ursprung

Utför följande steg i Azure portalen för att konfigurera Front Door-ursprunget:

  1. Skapa Front Door-profil
  2. Lägga till ursprungsgrupp med dina API-instanser för serverdelen
  3. Konfigurera hälsoprobning till /health slutpunkt
  4. Ange endast HTTPS-vidarebefordran
  5. Aktivera WAF-princip (valfritt)

Inställningar för hälsokontroll:

  • Sökväg: /health
  • Protokoll: HTTPS
  • Metod: GET
  • Intervall: 30 sekunder

Hantera flera regioner

När du distribuerar till flera regioner bakom Front Door lägger du till regionmedvetenhet för loggning och diagnostik:

// 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();
});

Verifiera tokens med Front Door

Om klienter begär token som är begränsade till Front Door-URL:en lägger du till den i listan över giltiga målgrupper:

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"]
    };
});

Integrera med Azure Application Gateway

Konfigurera ditt skyddade API bakom Azure Application Gateway med stöd för Web Application Firewall (WAF).

Konfigurera backend-API:t

Konfigurera de vidarebefordrade rubrikerna för Application Gateway i 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();

Konfigurera Application Gateway-inställningar

Ange följande inställningar för serverdel, hälsoavsökning och WAF i Azure-portalen:

Serverdelsinställningar:

  • Protokoll: HTTPS (rekommenderas) eller HTTP
  • Port: 443 eller 80
  • Åsidosätt backend-sökväg: Nej (om det inte behövs)
  • Anpassad sond: Ja, pekar på /health

Hälsoavsökning:

  • Protokoll: HTTPS eller HTTP
  • Värd: Lämna standard eller ange
  • Sökväg: /health
  • Intervall: 30 sekunder
  • Ohälsosam tröskelvärde: 3

WAF-policy:

  • Aktivera WAF med OWASP 3.2-regeluppsättning
  • Viktigt: Se till att JWT-token i Authorization rubriker inte blockeras
  • Du kan behöva skapa WAF-undantag för RequestHeaderNames som innehåller "Authorization"

Konfigurera sökvägsbaserad routning

När du använder sökvägsbaserade routningsregler konfigurerar du serverdels-API:et för att hantera sökvägsprefixet:

// 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();

Application Gateway-regel:

  • Sökväg: /api/v1/*
  • Serverdelsmål: Serverdelspoolen
  • Serverdelsinställningar: Använd konfigurerade inställningar

Felsökning av vanliga problem

Använd dessa lösningar för att lösa de vanligaste problemen när du distribuerar skyddade API:er bakom gatewayer.

Problem: 401 Ej auktoriserad efter distribution bakom en gateway

Symtom:

  • API:n fungerar lokalt men returnerar 401 när den används bakom gatewayen
  • Token verkar giltig när den avkodas vid jwt.ms

Möjliga orsaker:

  1. Inkompatibilitet mellan målgrupp och påstående

    # 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. Saknas mellanhandsprogram för vidarebefordrade headers

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

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

Lösning:

  • Aktivera felsökningsloggning för att visa information om tokenverifiering
  • Lägga till flera giltiga målgrupper i tokenverifiering
  • Kontrollera att X-Forwarded-* headers vidarebefordras av gateway

Problem: Hälsokontroller misslyckas

Symtom:

  • Gateway anger serverdelen som ohälsosam
  • Hälsoslutpunkten returnerar 401

Lösning:

Se till att hälsoslutpunkten körs innan mellanprogrammet för autentisering:

// 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

Problem: CORS-fel bakom Front Door

Symtom:

  • Preflight OPTIONS-begäranden misslyckas
  • Webbläsarkonsolen visar CORS-fel

Lösning:

Lägg till din Front Door och klientdelsursprung till CORS-policy:

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();

Problem: Varningar om vidarebefordrad header i loggar

Symtom:

Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersMiddleware: Unknown proxy

Lösning:

Rensa kända nätverk och proxyservrar för att acceptera vidarebefordrade huvuden från Azure infrastruktur:

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"));
});

Problem: APIM returnerar 401 men serverdelen returnerar 200

Symtom:

  • Token är giltigt för backend
  • APIM-policy validate-jwt fungerar inte

Lösning:

Kontrollera att APIM-princippubliken matchar tokenpubliken:

<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>

Problem: Flera autentiseringsscheman är i konflikt

Symtom:

  • Använda både JWT-ägarprogram och andra system
  • Fel schema har valts

Lösning:

Ange autentiseringsschemat explicit i kontrollanten:

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
{
    // ...
}

Följ metodtipsen

Använd dessa metoder för att skapa en säker, elastisk API-distribution bakom gatewayer.

1. Försvar på djupet

Verifiera alltid token i serverdels-API:et, även om gatewayen verifierar dem:

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

Gatewaykonfigurationen kan ändras och token kan spelas upp igen. Skydd på djupet är viktigt för säkerheten.

2. Använda hanterade identiteter för gateway-till-serverdelskommunikation

Om din gateway anropar serverdelen med en egen identitet konfigurerar du serverdelen så att den accepterar både användartoken och hanterade identitetstoken:

// 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)
    };
});

3. Övervaka gatewaymått

Spåra dessa nyckelmått för att hålla insyn i gateway-implementeringen:

  • Felfrekvenser för 401/403
  • Valideringsfel för token
  • Hälsoavsökningsfel
  • Vidarebefordrade rubriker (för felsökning)

4. Använd Application Insights

Lägg till Application Insights-telemetri för att logga gatewayspecifika begärandeegenskaper:

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. Åtskilj hälsa från färdiga

Använd distinkta slutpunkter för liveness-kontroller (körs tjänsten?) och beredskap-kontroller (kan tjänsten acceptera trafik?),

// 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. Dokumentera gateway-konfigurationen

Skapa en README- eller wiki-sida som dokumenterar:

  • Vilka gatewayer som används
  • Förväntningar hos tokenanvändare
  • CORS-konfiguration
  • Slutpunkter för hälsoavsökning
  • Konfiguration av vidarebefordrade rubriker
  • Procedurer för nödrullback

Skapa ett komplett exempel med Azure API Management

Det här avsnittet innehåller ett fullständigt, produktionsklart exempel på ett ASP.NET Core API bakom Azure API Management med Microsoft Entra ID autentisering.

Backend-API (ASP.NET Core)

Följande Program.cs konfigurerar vidarebefordrade huvuden, Microsoft Entra-autentisering, hälsokontroller och 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();

Lägg till följande Microsoft Entra- och Application Insights-konfiguration i 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"
  }
}

Följande kontroll kräver autentisering och loggar vidarebefordrade headers som en del av felsökning.

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-konfiguration

Följande inkommande princip verifierar JWT-token, tillämpar hastighetsbegränsning, vidarebefordrar huvuden och konfigurerar 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>