GraphQL API-Gateway-Patterns: Authentifizierung zentral lösen
AI generated
{ }
type
GraphQL · API-Gateway · Auth · Federation
GraphQL API-Gateway-Patterns
Authentifizierung zentral lösen

Wer Authentifizierung in jedem GraphQL-Subgraph einzeln implementiert, baut dieselbe JWT-Prüfung zehnmal, mit zehn potenziellen Fehlerquellen. Ein API-Gateway übernimmt Token-Validierung, Session-Handling und Rate-Limiting an einer einzigen Stelle und reicht nur einen geprüften Auth-Context an die dahinterliegenden Services weiter.

17 Min. Lesezeit JWT · Apollo Router · Auth-Context · Rate-Limiting GraphQL · Security · Microservices

1. Warum Auth nicht in jedem Service dupliziert werden sollte

Sobald ein GraphQL-System aus mehreren Subgraphs oder Microservices besteht, stellt sich die Frage, wo Authentifizierung geprüft wird. Die naheliegende, aber problematische Antwort lautet: in jedem einzelnen Service. Das führt dazu, dass dieselbe JWT-Validierungslogik, dasselbe Secret-Handling und dieselbe Fehlerbehandlung in fünf, zehn oder zwanzig Codebasen dupliziert wird. Ein API-Gateway löst genau dieses Problem, indem es Authentifizierung an einer einzigen, klar definierten Stelle zentralisiert, bevor eine Anfrage überhaupt einen der dahinterliegenden GraphQL-Services erreicht.

Der Vorteil eines zentralen API-Gateway-Patterns zeigt sich besonders bei Sicherheitsupdates: Wird eine Schwachstelle in der JWT-Bibliothek gefunden, muss nur das Gateway aktualisiert werden, nicht zwanzig Services parallel. Gleichzeitig sinkt das Risiko, dass ein einzelner Service versehentlich eine schwächere oder fehlerhafte Auth-Prüfung implementiert, weil die Prüfung selbst gar nicht mehr im Service liegt. Die folgenden Abschnitte zeigen konkrete Muster, wie ein API-Gateway diese Aufgabe für GraphQL-Architekturen übernimmt.

2. API-Gateway-Typen für GraphQL im Überblick

Drei Grundformen eines API-Gateway begegnen einem in GraphQL-Architekturen am häufigsten. Der einfache Reverse-Proxy leitet Requests unverändert an einen einzelnen GraphQL-Endpunkt weiter und übernimmt nur TLS-Terminierung, Header-Injection und grundlegende Auth-Prüfung, etwa mit Nginx oder Envoy vor einem monolithischen Magento-GraphQL-Endpunkt. Der Federation-Gateway, etwa Apollo Router oder GraphQL Mesh, komponiert mehrere Subgraph-Schemas zu einem einzigen, öffentlich sichtbaren Supergraph und verteilt Teilquery an die zuständigen Subgraphs.

Der dritte Typ, das Backend-for-Frontend-Gateway (BFF), unterscheidet sich fundamental: Es bündelt nicht mehrere GraphQL-Services zu einem Schema, sondern stellt für jeden Frontend-Typ, etwa Mobile-App und Web-Storefront, ein eigenes, zugeschnittenes GraphQL-Schema bereit, das intern mehrere Backend-Systeme aggregiert. Alle drei API-Gateway-Typen können Authentifizierung zentral übernehmen, unterscheiden sich aber darin, wie granular sie Auth-Entscheidungen pro Feld oder pro Subgraph treffen können.

3. JWT-Validierung zentral am Gateway

Die häufigste Form zentraler Authentifizierung an einem API-Gateway ist die JWT-Validierung: Das Gateway prüft Signatur, Ablaufdatum und Issuer eines mitgesendeten Bearer-Tokens, bevor die Anfrage überhaupt an einen GraphQL-Resolver weitergereicht wird. Schlägt die Validierung fehl, antwortet das Gateway direkt mit 401 Unauthorized, ohne dass ein Subgraph jemals von der Anfrage erfährt. Das reduziert Angriffsfläche, weil ungültige Tokens die internen Services gar nicht erst erreichen.

Wichtig ist, dass das Gateway den öffentlichen Schlüssel des Identity-Providers cached und regelmäßig über den JWKS-Endpunkt aktualisiert, statt bei jedem Request eine neue Anfrage an den Auth-Server zu stellen. Diese Trennung zwischen Token-Ausstellung, meist durch einen dedizierten Identity-Provider wie Keycloak oder Auth0, und Token-Validierung am API-Gateway ist ein Kernprinzip moderner Auth-Architekturen: Der Identity-Provider kennt Nutzer und Passwörter, das Gateway kennt nur den öffentlichen Schlüssel zur Signaturprüfung.


// gateway-jwt-middleware.js — validates JWTs before requests reach any subgraph
const { createRemoteJWKSet, jwtVerify } = require('jose');

const JWKS = createRemoteJWKSet(new URL('https://auth.mironsoft.de/.well-known/jwks.json'));

async function validateToken(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader?.startsWith('Bearer ')) {
    return res.status(401).json({ error: 'Missing bearer token' });
  }

  try {
    const token = authHeader.slice(7);
    const { payload } = await jwtVerify(token, JWKS, {
      issuer: 'https://auth.mironsoft.de',
      audience: 'graphql-api',
    });

    // Attach verified claims — subgraphs trust this, never re-validate the raw token
    req.authContext = { userId: payload.sub, roles: payload.roles ?? [] };
    next();
  } catch (err) {
    // Signature invalid, expired, or wrong issuer — reject before reaching any subgraph
    return res.status(401).json({ error: 'Invalid or expired token' });
  }
}

module.exports = { validateToken };

4. Auth-Context an Subgraphs weiterreichen

Nach erfolgreicher JWT-Validierung muss das API-Gateway die geprüften Informationen so an die dahinterliegenden Subgraphs weiterreichen, dass diese ihnen vertrauen können, ohne den Token erneut zu prüfen. Das übliche Muster: Das Gateway extrahiert Nutzer-ID und Rollen aus dem validierten Token und setzt sie als interne, signierte Header wie X-User-Id und X-User-Roles, bevor die Anfrage intern weitergeleitet wird. Subgraphs prüfen diese Header, nicht den ursprünglichen JWT, weil sie in einem vertrauenswürdigen internen Netzwerk hinter dem Gateway laufen.

Ein kritischer Sicherheitsaspekt dabei: Diese internen Header dürfen niemals direkt von externen Clients gesetzt werden können. Läuft ein Subgraph in einem Netzwerk, das theoretisch auch von außen erreichbar ist, muss das Gateway eingehende X-User-Id-Header aktiv entfernen, bevor es seine eigenen, geprüften Werte setzt. Sonst könnte ein Angreifer, der das Gateway umgeht, sich selbst beliebige Rollen zuweisen. Bei Apollo Federation übernimmt der Router diese Context-Propagation über rhai-Skripte oder Coprocessor-Hooks, die vor jedem Subgraph-Request laufen.


{
  "_comment": "Decoded JWT payload the gateway validates before forwarding a request",
  "sub": "customer-48213",
  "iss": "https://auth.mironsoft.de",
  "aud": "graphql-api",
  "roles": ["customer", "newsletter-subscriber"],
  "exp": 1798761600,
  "_forwarded_headers": {
    "X-User-Id": "customer-48213",
    "X-User-Roles": "customer,newsletter-subscriber",
    "_note": "set only by the gateway, stripped from any incoming external request"
  }
}

5. Session- vs. Token-basierte Auth am Gateway

Neben JWT-basierter Authentifizierung setzen manche API-Gateway-Architekturen auf klassische, serverseitige Sessions, besonders wenn ein bestehendes System wie Magento bereits Session-Cookies für den Storefront nutzt. In diesem Modell prüft das Gateway das Session-Cookie gegen einen zentralen Session-Store, meist Redis, und lädt daraus die zugehörigen Nutzerdaten, statt sie direkt aus einem Token zu dekodieren. Der Vorteil: Sessions lassen sich serverseitig sofort invalidieren, etwa bei einem Logout oder einer Sperrung, während ein einmal ausgestelltes JWT bis zu seinem Ablauf gültig bleibt, sofern keine zusätzliche Revocation-Liste geführt wird.

Der Nachteil von Session-basierter Auth am Gateway ist der zusätzliche Netzwerk-Hop zum Session-Store bei jedem Request, während ein JWT rein lokal validiert werden kann. In der Praxis kombinieren viele produktive API-Gateway-Setups beide Modelle: Kurzlebige Access-Tokens im JWT-Format für performante, zustandslose Validierung, kombiniert mit einer serverseitigen Session oder einem Refresh-Token-Store für die Möglichkeit, Zugriff jederzeit zu widerrufen.

6. Rate-Limiting und Auth kombinieren

Ein oft übersehener Vorteil eines zentralen API-Gateway: Rate-Limiting kann direkt an die geprüfte Identität gekoppelt werden, statt nur an die IP-Adresse. Ein authentifizierter Nutzer bekommt ein höheres Kontingent als ein anonymer Request, und unterschiedliche Rollen, etwa zahlende Kunden gegenüber Gästen, können unterschiedliche Limits erhalten. Diese Kombination aus Auth-Prüfung und Rate-Limiting funktioniert nur, wenn beide am selben Punkt in der Pipeline sitzen, weil das Rate-Limiting sonst die Nutzeridentität gar nicht kennt.

Für GraphQL kommt eine zusätzliche Dimension hinzu: Rate-Limiting sollte nicht nur die Anzahl der Requests zählen, sondern auch die Query-Complexity berücksichtigen, weil eine einzelne, tief verschachtelte GraphQL-Query mehr Backend-Last erzeugen kann als hundert einfache REST-Aufrufe. Ein API-Gateway, das JWT-Validierung, Rollen-Erkennung und Complexity-basiertes Rate-Limiting kombiniert, verhindert sowohl unautorisierten Zugriff als auch Resource-Exhaustion durch autorisierte, aber übermäßig komplexe Anfragen.

7. Praxisbeispiel: Apollo Router mit Coprocessor

Apollo Router, der moderne, in Rust geschriebene Federation-Gateway, bietet mit dem Coprocessor-Mechanismus einen klaren Weg, Authentifizierung als externen HTTP-Dienst einzubinden, statt sie fest im Router-Binary zu verdrahten. Der Router ruft vor jedem Subgraph-Request einen konfigurierten HTTP-Endpunkt auf, übergibt Header und Kontext, und erwartet zurück, ob die Anfrage fortgesetzt werden darf und welcher Auth-Context injiziert werden soll. Das entkoppelt die Auth-Logik komplett vom Router selbst und erlaubt, sie in einer beliebigen Sprache zu implementieren.

Alternativ unterstützt Apollo Router eingebettete rhai-Skripte für leichtgewichtige Logik direkt im Router-Prozess, ohne den Netzwerk-Overhead eines externen Coprocessor-Aufrufs. Für reine JWT-Validierung ohne komplexe Zusatzlogik ist das eingebaute authentication-Plugin des Routers meist ausreichend und performanter als ein externer Coprocessor, während komplexere Szenarien wie dynamisches Rollen-Mapping aus einem externen Identity-Provider eher für den Coprocessor-Ansatz sprechen.


# router.yaml — Apollo Router: built-in JWT auth plus a coprocessor for custom logic
authentication:
  router:
    jwt:
      jwks:
        - url: https://auth.mironsoft.de/.well-known/jwks.json
      header_name: Authorization
      header_value_prefix: "Bearer "

coprocessor:
  url: http://auth-coprocessor:8081
  router:
    request:
      headers: true
  subgraph:
    all:
      request:
        headers: true
        context: true

rate_limit:
  # Complexity-aware limiting combined with the authenticated identity
  global:
    capacity: 1000
    interval: 60s
  per_user:
    capacity: 200
    interval: 60s

#!/usr/bin/env bash
# test-gateway-auth.sh — verify the gateway rejects invalid tokens before subgraphs see them
set -euo pipefail

GATEWAY_URL="https://api.mironsoft.de/graphql"
QUERY='{"query":"{ product(sku: \"TEST-001\") { name } }"}'

echo "[TEST] Request without token — expect 401"
curl -s -o /dev/null -w "%{http_code}\n" -X POST "$GATEWAY_URL" \
  -H "Content-Type: application/json" -d "$QUERY"

echo "[TEST] Request with expired token — expect 401"
curl -s -o /dev/null -w "%{http_code}\n" -X POST "$GATEWAY_URL" \
  -H "Authorization: Bearer $EXPIRED_TOKEN" \
  -H "Content-Type: application/json" -d "$QUERY"

echo "[TEST] Request with valid token — expect 200"
curl -s -o /dev/null -w "%{http_code}\n" -X POST "$GATEWAY_URL" \
  -H "Authorization: Bearer $VALID_TOKEN" \
  -H "Content-Type: application/json" -d "$QUERY"

8. Gateway-Pattern vor Magento GraphQL

Magentos eigener GraphQL-Endpunkt bringt zwar eigene Authentifizierung über Customer-Token und Admin-Token mit, in produktiven Headless-Architekturen sitzt davor aber häufig zusätzlich ein API-Gateway, das mehrere Backend-Systeme, etwa Magento für Produktdaten und ein separates CMS für Content, hinter einem einzigen Supergraph zusammenführt. In diesem Setup validiert das Gateway den Nutzer-Token einmalig und reicht ihn dann entweder unverändert an Magento weiter, das seine eigene Token-Prüfung durchführt, oder tauscht ihn gegen einen internen Magento-Customer-Token aus, den nur das Gateway kennt.

Der zweite Ansatz, Token-Exchange am Gateway, hat einen wichtigen Sicherheitsvorteil: Der öffentlich sichtbare Zugriffstoken, den ein Frontend erhält, unterscheidet sich vom internen Magento-Token, der niemals das Gateway verlässt. Selbst wenn der öffentliche Token kompromittiert würde, bliebe der interne Magento-Zugriff geschützt, solange die Token-Exchange-Logik selbst sicher implementiert ist. Für Magento-Projekte mit mehreren Frontend-Typen ist dieses Muster der Standardweg, um Authentifizierung nicht in jedem einzelnen Headless-Client neu zu implementieren.


# Federated query — the router splits this across subgraphs, injecting the
# same verified auth context into each subgraph request automatically
query CustomerDashboard {
  customer {
    # resolved by the "accounts" subgraph, using X-User-Id from the gateway
    id
    email
    orders {
      # resolved by the "orders" subgraph, same trusted context, no re-auth
      id
      total
      status
    }
  }
}

9. Gateway-Auth-Patterns im Vergleich

Die folgende Tabelle vergleicht die wichtigsten Muster zur zentralen Authentifizierung an einem GraphQL-API-Gateway.

Pattern Vorteil Nachteil
JWT-Validierung am Gateway Zustandslos, schnell, keine Session-Store-Abfrage Keine sofortige Revocation ohne Zusatzmechanismus
Session-basiert am Gateway Sofortige Invalidierung möglich Zusätzlicher Netzwerk-Hop pro Request
Externer Coprocessor Sprach- und Team-unabhängig, flexibel erweiterbar Zusätzliche Netzwerk-Latenz pro Subgraph-Request
Token-Exchange am Gateway Interner Token bleibt vom Frontend isoliert Zusätzliche Komplexität im Gateway-Code

Kein Pattern ist universell richtig. JWT-Validierung eignet sich für die meisten performance-kritischen Szenarien, während Session-basierte Auth dort sinnvoll ist, wo sofortige Widerrufbarkeit Pflicht ist, etwa bei Admin-Zugängen. Token-Exchange lohnt sich besonders in Multi-Backend-Architekturen mit Magento und weiteren Systemen hinter einem gemeinsamen API-Gateway.

Mironsoft

GraphQL-Gateway-Architektur und Auth-Konzepte

Authentifizierung für eure GraphQL-Landschaft zentralisieren?

Wir konzipieren und implementieren API-Gateway-Architekturen für GraphQL, von JWT-Validierung über Token-Exchange bis zu Complexity-basiertem Rate-Limiting, inklusive Anbindung an Magento und weitere Backend-Systeme.

Gateway-Konzeption

Passenden Gateway-Typ und Auth-Pattern für eure Architektur auswählen

Apollo Router Setup

JWT-Auth, Coprocessor und Rate-Limiting produktionsreif konfigurieren

Magento-Integration

Token-Exchange zwischen Gateway und Magento Customer-Token einrichten

10. Zusammenfassung

Ein zentrales API-Gateway löst Authentifizierung für GraphQL-Architekturen an genau einer Stelle, statt sie in jedem Subgraph zu duplizieren. JWT-Validierung mit gecachten JWKS-Schlüsseln bildet dabei meist die Basis, ergänzt um sicher weitergereichten Auth-Context in internen Headern, die von externen Clients nicht direkt gesetzt werden können. Session-basierte Auth bleibt relevant, wo sofortige Widerrufbarkeit zählt, und lässt sich mit JWT-basierten Access-Tokens kombinieren.

Apollo Router zeigt mit seinem Coprocessor- und rhai-Mechanismus, wie sich Auth-Logik von der Gateway-Infrastruktur entkoppeln lässt, ohne auf Performance zu verzichten. Für Magento-Projekte mit mehreren Frontend-Typen ist Token-Exchange am Gateway das wirksamste Muster, um den internen Magento-Zugriff vom öffentlich sichtbaren Token zu isolieren. In Kombination mit Complexity-basiertem Rate-Limiting entsteht so ein API-Gateway, das sowohl unautorisierten Zugriff als auch Resource-Exhaustion zuverlässig verhindert.

GraphQL API-Gateway-Patterns für Auth — Das Wichtigste auf einen Blick

JWT-Validierung

Zentral am Gateway prüfen, gecachte JWKS-Schlüssel nutzen, ungültige Tokens früh abweisen.

Auth-Context

Nur intern gesetzte, geprüfte Header an Subgraphs weiterreichen, niemals extern überschreibbar.

Rate-Limiting

An Identität und Query-Complexity koppeln, nicht nur an die IP-Adresse.

Token-Exchange

Öffentlichen Token vom internen Backend-Token trennen, etwa bei Magento-Integrationen.

11. FAQ: GraphQL API-Gateway-Patterns

1Warum Auth am Gateway?
Vermeidet Duplikation, reduziert Angriffsfläche, macht Sicherheitsupdates einfacher, weil nur eine Stelle aktualisiert wird.
2JWT vs. Session am Gateway?
JWT zustandslos ohne Netzwerk-Hop, aber nicht sofort widerrufbar. Session sofort widerrufbar, aber mit zusätzlichem Store-Zugriff.
3Auth sicher an Subgraphs weiterreichen?
Über interne Header wie X-User-Id, wobei eingehende externe Header gleichen Namens vorher entfernt werden müssen.
4Was ist ein Coprocessor?
Externer HTTP-Dienst, den Apollo Router vor jedem Subgraph-Request aufruft, um Auth-Logik außerhalb des Routers zu implementieren.
5Coprocessor oder eingebautes Plugin?
Für reine Validierung reicht das eingebaute Plugin. Coprocessor bei komplexerem, dynamischem Rollen-Mapping.
6Auth mit Rate-Limiting kombinieren?
Rate-Limit an geprüfte Identität koppeln, zusätzlich gewichtet nach Query-Complexity statt reiner Request-Anzahl.
7Was ist Token-Exchange?
Gateway tauscht öffentlichen Token gegen internen Backend-Token, der niemals das Gateway verlässt.
8Braucht Magento ein extra Gateway?
Für Magento-only oft nicht. Bei mehreren Backends hinter einem gemeinsamen Supergraph übernimmt ein Gateway sinnvoll die Auth-Rolle.
9JWKS-Schlüssel aktuell halten?
Gateway cached öffentliche Schlüssel vom JWKS-Endpunkt und aktualisiert sie periodisch statt pro Request.
10Pattern für Admin-Zugänge?
Session-basierte Auth, weil Admin-Zugänge bei Verdacht sofort widerrufbar sein müssen.