Je eigen API beveiligen: authenticatie en autorisatie voor je eigen gebruikers
Veel technische documentatie over taalmodellen richt zich uitsluitend op het veilig opslaan van upstream provider-sleutels voor partijen als OpenAI, Anthropic of Mistral. Maar wie een AI-gedreven applicatie in productie neemt, bouwt vrijwel altijd een eigen backend of gateway die door interne microservices, mobiele apps of externe SaaS-klanten wordt aangeroepen. Voor de upstream communicatie lees je het ankerartikel over hoe je API-sleutels voor LLM's veilig kunt beheren, maar aan de downstream-zijde ontstaat een fundamenteel ander vraagstuk: hoe verifieer je wie de aanroeper is en hoe begrens je wat die gebruiker mag consumeren?
Een LLM-endpoint verschilt wezenlijk van een traditioneel REST-endpoint. Waar een reguliere CRUD-operatie voorspelbare serverrekenkracht vraagt, brengt een ongecontroleerde prompt direct variabele kosten, asynchrone rekentijd en potentiële datalekken met zich mee. Authenticatie en autorisatie vormen daarom niet alleen een beveiligingslaag voor datatoegang, maar functioneren tevens als de financiële en operationele rem op je systeem. In dit artikel behandelen we de architectuur, tokenstructuren, fijnmazige permissiemodellen en praktische middlewarepatronen om je eigen downstream LLM-API waterdicht te beveiligen.
De architectonische scheiding: upstream versus downstream
In een robuuste AI-architectuur bestaan altijd twee strikt gescheiden vertrouwensdomeinen. Aan de upstream-zijde communiceert de backend met de foundation model providers. Deze communicatie maakt gebruik van geheime, langlevende API-sleutels die onder geen beding aan clients mogen worden blootgesteld. Aan de downstream-zijde praten browsers, mobiele applicaties en externe integratiepartners met jouw eigen API-gateway. Hier gelden kortlevende sessies, strikte identiteitscontroles en fijnmazige rechten.
Wanneer een client direct een upstream provider zou aanroepen met een gedeelde sleutel, verlies je elk inzicht in individueel gebruikersgedrag en kan een kwaadwillende actor je volledige tokenquota leegtrekken. De eigen API fungeert als beschermende tussenlaag (de reverse proxy of gateway) die binnenkomende verzoeken ontleedt, valideert, verrijkt en autoriseert voordat er ook maar één token naar een extern model wordt verzonden.
| Eigenschap | Upstream authenticatie (Provider) | Downstream authenticatie (Eigen API) |
|---|---|---|
| Doel | Toegang tot ruwe model-GPU's en endpoints | Toegang tot applicatielogica, tools en context |
| Identiteit | Eén centrale organisatie of service-account | Individuele eindgebruiker, tenant of API-consument |
| Levensduur token | Langlevend (maanden tot rotatie) | Kortlevend (minuten tot uren via JWT/OIDC) |
| Controlemechanisme | Statische bearer tokens of cloud IAM | Dynamische scopes, RBAC, ABAC en budgetcaps |
Authenticatiemechanismen: API-sleutels, OAuth2 en JWT's
De keuze voor het authenticatiemechanisme hangt af van het type client dat verbinding maakt. Voor machine-to-machine (M2M) communicatie, zoals achtergrondservices of externe ontwikkelaars die jouw AI-pijplijn via code integreren, zijn hashed API-sleutels de industriestandaard. Voor interactieve webapplicaties en mobiele clients is een tokengebaseerd model via OpenID Connect (OIDC) en OAuth2 met JSON Web Tokens (JWT) de aangewezen route.
Bij het uitgeven van eigen API-sleutels voor ontwikkelaars mag de sleutel nooit in leesbare tekst (plaintext) in de database worden opgeslagen. Sla uitsluitend een cryptografische hash op (zoals SHA-256) en toon de geheime sleutel slechts eenmalig bij creatie. Geef de sleutel een herkenbaar prefix (bijvoorbeeld llm_live_...) zodat geautomatiseerde scanners van secret leaks de sleutel direct kunnen identificeren en blokkeren.
Voor gebruikerssessies biedt een ondertekend JWT-formaat grote voordelen omdat de gateway cryptografisch kan controleren of het token geldig is zonder bij elk binnenkomend streaming-chunk de centrale authenticatiedatabase te bevragen. Zorg er wel voor dat asymmetrische algoritmes zoals RS256 of EdDSA worden gebruikt, zodat verificatieservers alleen de publieke sleutel nodig hebben.
Fijnmazige autorisatie: van RBAC naar Scopes en ABAC
Authenticatie stelt vast wie de aanroeper is; autorisatie bepaalt wat diegene mag uitvoeren. Binnen LLM-toepassingen volstaat een traditioneel rolgebaseerd model (RBAC) met simpele rollen als 'admin' en 'user' zelden. De variatie in rekenkracht, kosten en gevoeligheid van tools vereist fijnmazige permissies (scopes) of attribuutgebaseerde toegangscontrole (ABAC).
Definieer scopes die expliciet aangeven welke acties een token mag initiëren. Typische voorbeelden zijn:
models:cheap:invoke: Toegang tot snelle, goedkope modellen voor routinetaken.models:reasoning:invoke: Toegang tot dure redeneermodellen met uitgebreide chain-of-thought capaciteit.tools:database:read: Toestemming voor de LLM om functies aan te roepen die interne databronnen uitlezen.tools:system:execute: Zeer restrictieve scope voor acties die externe wijzigingen doorvoeren (mutaties, e-mails verzenden, code uitvoeren).
Met Attribute-Based Access Control (ABAC) kun je aanvullende dynamische regels opleggen. Zo kan een junior medewerker wel de scope hebben om een samenvatting te genereren, maar weigert het autorisatiefilter de aanroep zodra het contextdocument gemarkeerd is met het label 'vertrouwelijk' of zodra de aanroep buiten kantooruren plaatsvindt.
Multi-tenant isolatie en context-injectie op gateway-niveau
In een SaaS-omgeving waarin meerdere klanten op dezelfde infrastructuur draaien, is het isoleren van data cruciaal. Zonder strikte scheiding bestaat het gevaar dat embeddings of systeeminstructies van de ene tenant per ongeluk worden geïnjecteerd in de prompt van een andere gebruiker. Bekijk voor een diepere duik in architecturele datascheiding het artikel over multi-tenant LLM-applicaties bouwen, waarin tenant-isolatie en datapartitionering uitvoerig worden toegelicht.
De authenticatie-middleware moet bij elke aanroep de tenant_id extraheren uit de gevalideerde claims van het token. Deze identifier wordt vervolgens hard gekoppeld aan de context van het request. Dit garandeert dat alle downstream zoekacties in vector-indices, documentopslag en gespreksgeschiedenis automatisch worden gefilterd op de betreffende tenant, zonder dat de client deze parameter zelfstandig kan manipuleren.
# Voorbeeld van generieke middleware-autorisatie in Python (FastAPI/Starlette stijl)
import time
import hmac
import hashlib
from typing import Optional, Set
from dataclasses import dataclass
@dataclass
class AuthContext:
user_id: str
tenant_id: str
scopes: Set[str]
max_cost_limit_cents: int
class LLMAuthorizationError(Exception):
"""Foutmelding bij ontoereikende rechten of budgetoverschrijding."""
pass
def authorize_llm_request(
auth: AuthContext,
required_model_tier: str,
requested_tools: list[str],
estimated_cost_cents: int
) -> None:
# 1. Controleer modelpermissie
required_scope = f"models:{required_model_tier}:invoke"
if required_scope not in auth.scopes and "admin:all" not in auth.scopes:
raise LLMAuthorizationError(
f"Geen toegang tot modeltier '{required_model_tier}'. Vereist: {required_scope}"
)
# 2. Controleer tool-permissies
for tool in requested_tools:
tool_scope = f"tools:{tool}:execute"
if tool_scope not in auth.scopes and "admin:all" not in auth.scopes:
raise LLMAuthorizationError(f"Geen toestemming voor tool: {tool}")
# 3. Controleer harde financiële limiet per request
if estimated_cost_cents > auth.max_cost_limit_cents:
raise LLMAuthorizationError("Aanvraag overschrijdt maximaal toegestane transactiekosten.")
Token-budgettering en per-user quota handhaving
Een cruciaal aspect van autorisatie bij AI-backends is budgetbeheer. Waar standaard web-API's rate limits uitdrukken in 'verzoeken per seconde' (RPS), vereisen LLM-systemen limieten op basis van verbruikte tokens en gemaakte kosten. Een gebruiker die tien korte prompts stuurt van elk 50 tokens belast het systeem aanzienlijk minder dan een gebruiker die één document van 100.000 tokens verwerkt.
Implementeer daarom een tweeledig controlesysteem:
- Pre-flight schatting: Voordat de prompt naar de upstream provider gaat, berekent een lokale tokenizer de omvang van de invoer plus het maximale aantal gereserveerde output-tokens (
max_tokens). De autorisatielaag controleert in een snelle in-memory store (zoals Redis) of het saldo van de gebruiker toereikend is. - Post-execution verrekening: Zodra de LLM-aanroep voltooid is of de stream stopt, leest de gateway de daadwerkelijk gerapporteerde
usage-statistieken uit en wordt het exacte verbruik direct gecorrigeerd in de administratie.
Mocht een gebruiker zijn quotum overschrijden, dan retourneert de API een expliciete 429 Too Many Requests of 402 Payment Required statuscode, inclusief een header die aangeeft wanneer het tegoed weer wordt aangevuld.
Invoervalidatie en sessie-hygiëne
Authenticatie houdt ongeautoriseerde gebruikers buiten de deur, maar beschermt niet tegen kwaadwillende instructies van geauthenticeerde accounts. Prompt-injecties en data-exfiltratiepogingen kunnen via geautoriseerde kanalen binnendringen. Lees ter aanvulling het overzicht over invoervalidatie en outputfiltering voor LLM-integraties om te zien hoe je prompts structureert en modeluitvoer sanitizeert.
Koppel daarnaast authenticatiestatus aan contextbeperking. Een geverifieerde sessie mag nooit ongefilterd systeem-prompts overschrijven. Sla de kerninstructies van je applicatie altijd veilig op aan de serverzijde en combineer deze via strikte templates met de gevalideerde invoer van de gebruiker. Zo voorkom je dat een geauthenticeerde aanvaller via manipulatie van headers of parameters de interne systeemprompt kan omzeilen.
Sessie-intrekking, sleutelrotatie en zero-trust validatie
In gedistribueerde systemen brengt het gebruik van stateless JWT's een bekend risico met zich mee: het intrekken van een sessie voordat het token verloopt is lastig. Omdat LLM-aanroepen financieel kostbaar zijn, kan een gecompromitteerd token binnen enkele minuten grote schade aanrichten. Werk daarom met zeer korte token-levensduren (bijvoorbeeld 5 tot 15 minuten) in combinatie met een centrale intrekkingslijst (revocation list of blocklist) in een snelle key-value store.
Voor API-sleutels van ontwikkelaars is geautomatiseerde rotatie noodzakelijk. Ondersteun altijd een overgangsperiode waarin zowel de oude als de nieuwe sleutel gelijktijdig actief zijn (dual-key window), zodat integratiepartners hun systemen zonder downtime kunnen updaten.
Bovendien moet de interne communicatie tussen je gateway en achterliggende workers worden ingericht volgens het zero-trust principe. Vertrouw er niet op dat een verzoek legitiem is puur omdat het van een intern IP-adres komt. Pas wederzijdse TLS-authenticatie (mTLS) toe tussen interne componenten en geef per service uitsluitend de minimaal benodigde upstream-rechten mee.
Wanneer je kiest voor strikte gegevensminimalisatie en geen gegevens bij upstream providers wilt achterlaten, lees dan de handleiding over zero-data-retention configureren bij LLM-API's om te zien hoe je dataretentie contractueel en technisch uitschakelt.
Privacy en compliance bij gebruikersverificatie
Bij het loggen van authenticatie-events ontstaat een spanningsveld met privacywetgeving. Om misbruik te detecteren wil je weten welke gebruiker welk verzoek heeft ingediend, maar het opslaan van volledige prompts gekoppeld aan herleidbare persoonsgegevens brengt aanzienlijke AVG-risico's met zich mee. Raadpleeg voor de juridische kaders en privacy-afwegingen het artikel over AI-modellen en privacy binnen AVG-compliance op het hub-subdomein.
Hanteer in de audit-logging van je eigen API een strikte scheiding tussen identiteitsdata en payload-inhoud. Log de user_id, tenant_id, tijdstempel, tokenverbruik en HTTP-status in een beveiligde audit-database. Maskeer of hasht gevoelige identifiers en bewaar prompt-inhoud alleen als dat strikt noodzakelijk is voor compliance, voorzien van een automatische verwijderingstermijn (retention policy).
Faalmodi, meetmethoden en operationele afwegingen
Elk beveiligingsmechanisme introduceert potentiële faalpunten en overhead. Het is essentieel om deze faalmodi te onderkennen, continu te meten en gerichte mitigaties door te voeren.
1. Latency-overhead door verificatie:
- Faalmodus: Complexe autorisatiecontroles (zoals het ophalen van gebruikersprofielen uit een relationele database en het berekenen van saldo's) voegen tientallen milliseconden toe aan de time-to-first-token (TTFT).
- Detectie: Meet de middleware-duur afzonderlijk via OpenTelemetry spans vóórdat het upstream verzoek vertrekt.
- Mitigatie: Valideer cryptografische JWT-signatures lokaal in het geheugen en gebruik gedistribueerde in-memory caches voor rate-limit tellers.
- Kosten: Vraagt extra RAM-capaciteit op de gateway-nodes en introduceert eventuele synchronisatie-vertragingen van enkele milliseconden tussen nodes.
2. Race conditions bij streaming en budgetuitputting:
- Faalmodus: Een gebruiker start tien parallelle streaming-verzoeken. Omdat de exacte kosten pas na afloop bekend zijn, overschrijdt de gebruiker het budget aanzienlijk voordat de tellers worden bijgewerkt.
- Detectie: Vergelijk periodiek het geregistreerde budgetsaldo met het werkelijk gefactureerde providerverbruik per gebruiker.
- Mitigatie: Reserveer vooraf een vast tokenbedrag (bijvoorbeeld de waarde van
max_tokens) op het saldo en geef niet-gebruikte tokens direct vrij zodra de stream sluit. Breek actieve SSE-streams direct af zodra het saldo tijdens het streamen nul bereikt. - Kosten: Verhoogde complexiteit in de state-machine van de gateway en mogelijke vroegtijdige afwijzing van legitieme verzoeken als gebruikers een te hoge
max_tokensinstellen.
3. Cascading failures bij uitval van de authenticatieprovider:
- Faalmodus: De centrale identity provider (IdP) is traag of onbereikbaar, waardoor alle binnenkomende LLM-aanroepen vastlopen op timeout-fouten.
- Detectie: Monitor het foutpercentage op authenticatie-endpoints (HTTP 500/504) los van upstream model-fouten.
- Mitigatie: Pas agressieve caching toe op publieke sleutelsets (JWKS) en configureer circuit breakers die gecontroleerde foutmeldingen teruggeven in plaats van wachtrijen te laten vollopen.
- Kosten: Korte vertraging bij het doorvoeren van ingetrokken sleutels zolang de JWKS-cache geldig blijft.
Conclusie en implementatievolgorde
Het beveiligen van je eigen LLM-API vraagt om meer dan het simpelweg afschermen van een URL met een wachtwoord. Door een duidelijke scheiding aan te brengen tussen upstream provider-sleutels en downstream gebruikers-tokens, bouw je een gecontroleerde omgeving waarin kosten, datatoegang en functionaliteit nauwgezet worden beheerd.
Begin bij de implementatie altijd met een robuuste JWT- of API-key-validatie in combinatie met strikte tenant-isolatie op gateway-niveau. Voeg vervolgens fijnmazige scopes toe voor modeltiers en gereedschappen, en sluit af met dynamische token-budgettering en real-time streaming-afbreking. Daarmee bescherm je niet alleen je intellectuele eigendom en gebruikersdata, maar houd je ook de operationele kosten van je AI-infrastructuur volledig onder controle.


