PAS7 Studio

Auth-Middleware in Bun.js: JWT, Sessions, API Keys und Multi-Tenant-Context ohne Chaos

Ein praktischer Deep Dive zu Auth-Middleware in Bun.js: wie man JWT-, Session- und API-Key-Prüfungen baut, wo Tenant Context gespeichert werden sollte, wie man 401/403 trennt, was man cachen kann, wie Token-Leaks vermieden werden und welche Best Practices von OWASP, Hono und Elysia sinnvoll sind.

14. Mai 2026· 14 Min. Lesezeit· Technologie
Geeignet fürBackend EngineersFull-Stack-EntwicklerTech LeadsTeams, die SaaS oder interne APIs auf Bun bauen
Technische Illustration einer Auth-Middleware-Pipeline in Bun.js mit Token, Session, API Key und Tenant Context

Die gefährlichsten Auth-Bugs sehen selten so aus: „Ein Nutzer ohne Token kam ins System.“ Häufiger ist der Token gültig, die Session existiert, der API Key ist echt, aber die Middleware hat den Request an den falschen Tenant gebunden, einen Scope nicht geprüft, 401 und 403 verwechselt oder ein Secret geloggt.

Bun gibt dir einen schnellen HTTP Layer, aber Auth ist kein Runtime Trick. Auth ist ein Contract: welche Credentials akzeptiert werden, wo sie gespeichert sind, wie sie validiert werden, wer User Context erstellt, wo Authorization beginnt und wie das alles getestet wird.

In diesem Artikel bauen wir nicht „noch ein Login Tutorial“. Wir zerlegen Production Patterns für Auth-Middleware in Bun APIs.

JWT, Sessions und API Keys haben unterschiedliche Failure Modes.
Authentication und Authorization sollten nicht in eine globale Middleware gemischt werden.
Tenant Context muss explizit aus Credential und Policy abgeleitet werden, nicht aus einem beliebigen Header.
Tokens und Cookies sollten in Logs so behandelt werden, als gäbe es sie dort gar nicht.

Das ist das zweite Chapter der Serie über Bun Middleware. Das erste hat das allgemeine Pipeline-Modell erklärt; dieses fokussiert sich auf den Auth Layer: wo er dünn bleiben sollte, wo er Storage braucht und wo er keine Middleware mehr ist.

Das mentale Modell einer Auth Pipeline: extract credential, verify, resolve subject, resolve tenant, attach context, continue oder reject.
JWT Middleware: wann sie passt, welche Claims geprüft werden sollten und warum decode ohne Verify keine Auth ist. [4]
Session Middleware: Cookies, HTTPS, Secure Attributes, Session Store und Logout Semantics. [1][5]
API Keys: hashed storage, scopes, rotation, owner metadata und Machine-to-Machine Access.
Hono und Elysia: wann built-in Middleware/Plugins reichen und wann man einen eigenen thin layer schreiben sollte. [2][3][6][7]
Schlechte Praktiken: Tokens in localStorage/logs, globaler DB Lookup, Tenant aus Header ohne Prüfung, langlebige JWT ohne Revocation Story.

Authentication beantwortet die Frage: „Wer oder was macht diesen Request?“ Authorization beantwortet: „Darf dieses Subject genau diese Aktion auf genau dieser Ressource ausführen?“ Middleware sollte oft den ersten Teil erledigen und Context für den zweiten vorbereiten.

Gute Auth-Middleware erstellt ein auth object: subjectId, subjectType, tenantId, scopes, sessionId, authMethod, requestId. Sie sollte aber nicht alle Business Rules des Produkts kennen. Zum Beispiel ist canUpdateInvoice(invoiceId) besser in Route oder Use Case aufgehoben, weil dort der Resource Context existiert.

Wenn globale Middleware „alles prüft“, entsteht eine Policy Engine ohne Schemas, Tests und Visibility. Wenn Middleware zu dünn ist, beginnt jede Route selbst Headers und Cookies zu lesen. Der Balancepunkt ist ein dünner Auth Context plus explizite Authorization nahe an der Business-Aktion.

Auth-Middleware lässt sich am besten als State Machine verstehen: Credential wird extrahiert, geprüft, in Subject und Tenant Context umgewandelt, danach wird der Request erlaubt oder abgelehnt.

Screenshot des Abschnitts auth-vs-authorization

Praktische Regel

Middleware sollte sagen, wer gekommen ist und mit welchem Basiskontext. Ob dieses Subject eine konkrete Aktion ausführen darf, sollte Route, Guard oder Use Case entscheiden.

Es gibt nicht den einen „richtigen“ Auth-Mechanismus. Es gibt unterschiedliche Trade-offs: stateless Verification, kontrollierter Logout, Machine-to-Machine Access, Rotation, Revocation und UX.

MechanismusWann geeignetWas prüfenHauptrisiko
JWT access tokenMobile/API Clients, Service-to-Service, verteilte Verificationexp, iss, aud, signature, algorithm, subject, scopesSchwieriges Revocation-Modell und die Versuchung, langlebige Tokens zu erstellen
Server-side sessionBrowser Apps, Dashboards, SaaS, wo kontrollierter Logout nötig istSession id in secure cookie, session store, expiry, device/risk metadataSession Fixation, unsichere Cookies, schwaches Store Cleanup
API keyIntegrationen, Webhooks, interne Automationen, Machine ClientsHashed key lookup, scope, owner, environment, last used, rotationPlaintext Key Storage und Keys ohne Scopes oder Expiry Policy
HybridBFF, Enterprise SaaS, Admin Panels plus Public APISession für Browser, JWT/API Keys für ServicesUnterschiedliche Auth-Modelle ohne einheitliches Audit und Error Contract

JWT, Sessions und API Keys lösen unterschiedliche Aufgaben: stateless access, Browser Logout Control und Machine-to-Machine Access.

Screenshot des Abschnitts credential-map

Kurz gesagt

Für Browser SaaS startet man meistens mit Sessions. Für externe APIs passen API Keys oder kurzlebige JWT. Für verteilte Systeme: JWT plus Revocation oder Introspection dort, wo das Risiko hoch ist.

In nativem Bun.serve kannst du einen Auth Layer ohne Framework bauen. Wichtig ist, keinen globalen State zu mutieren und Context nicht in module-level Variablen zu verstecken. Gib Context explizit weiter: entweder über einen Wrapper oder über einen eigenen AppRequestContext.

Ein einfacher Pattern sieht so aus:

TS
type AuthContext = {
  subjectId: string;
  tenantId: string;
  scopes: string[];
  method: "jwt" | "session" | "api-key";
};

type AppContext = { auth: AuthContext | null; requestId: string };
type Handler = (req: Request, ctx: AppContext) => Promise<Response> | Response;

type Middleware = (next: Handler) => Handler;

const unauthorized = () =>
  Response.json({ error: "unauthorized" }, { status: 401 });

const withAuth: Middleware = (next) => async (req, ctx) => {
  const header = req.headers.get("authorization");

  if (!header?.startsWith("Bearer ")) return unauthorized();

  const token = header.slice("Bearer ".length);
  const auth = await verifyAccessToken(token);

  if (!auth) return unauthorized();

  return next(req, { ...ctx, auth });
};

Bun.serve({
  fetch: withAuth(async (_req, ctx) => {
    return Response.json({ subjectId: ctx.auth?.subjectId });
  }),
});

Dieses Beispiel zeigt bewusst keine Implementierung von verifyAccessToken, weil sie von deiner JWT-/Session-/API-Key-Lösung abhängt. Wichtig ist die Form: Middleware liest keine Business Resource, prüft keine Permissions auf invoice/project/order und erzeugt keine Side Effects. Sie erstellt Auth Context oder gibt 401 zurück.

Was hier wichtig ist

Context muss request-scoped und explizit sein. Wenn Auth State in einer globalen Variable, einem Singleton oder einem mutable module object lebt, entsteht ein Leakage-Risiko zwischen Requests.

Bun hat eine eingebaute Cookie API für HTTP Server Routes: BunRequest enthält cookies, und geänderte Cookies werden in Routes automatisch auf die Response angewendet. Das ist praktisch für Session Cookies, Logout und Refresh Flows. [1]

Aber die Cookie API löst keine Security Policy. Die OWASP Session Guidance betont HTTPS für die gesamte Session, das Secure Cookie Attribute, begrenzte Persistenz, Kontrolle des Session Lifecycle und Reauthentication nach risikoreichen Events. [5]

Für Browser Auth in Bun sollte man Sessions als server-side State designen: Das Cookie enthält eine undurchsichtige Session ID, während Permissions, Tenant und Risk Metadata im Session Store leben. Das ermöglicht kontrollierten Logout, Rotation, Device Tracking und Session Revocation ohne auf JWT Expiry warten zu müssen.

Session Baseline

Das Cookie sollte httpOnly, secure, korrektes sameSite, engen path, klare TTL und einen server-side Session Store haben. Lege keine sensiblen User Data direkt ins Cookie.

Wenn du nicht den kompletten Auth Layer selbst schreiben willst, bieten Hono und Elysia fertige Primitives. Aber fertige Middleware ersetzt nicht deine Regeln für issuer, audience, scopes, tenant und error contract.

Hono jwt() prüft den Token und legt den Payload über c.get('jwtPayload') in den Context; die Middleware sucht den Authorization Header, wenn keine Cookie Option konfiguriert ist. [2]
Hono JWT Auth Middleware
Hono bearerAuth() eignet sich für API Tokens und bietet verifyToken, custom errors, realm, prefix und headerName. [3]
Hono Bearer Auth Middleware
Elysia hat ein JWT Plugin für Signing/Verification in Handlers und ein Bearer Plugin zum Extrahieren des Bearer Tokens. Das passt gut zum Elysia Lifecycle. [6][7]
Elysia JWT und Bearer Plugins

Kurz gesagt

Built-in Middleware ist sinnvoll für Parsing und grundlegende Verification. Tenant Resolution, Scopes, Audit und Business Authorization bleiben aber Application Design.

In SaaS sieht der häufigste Auth-Fehler nicht aus wie „kein Token“, sondern wie „ein valid user konnte in einem fremden Tenant arbeiten“. Der Grund ist simpel: Die Middleware hat x-tenant-id aus dem Request genommen und nicht geprüft, ob das Subject wirklich Zugriff auf diesen Tenant hat.

Tenant Context muss aus dem Credential abgeleitet oder gegen server-side Membership geprüft werden. Wenn Nutzer Tenants wechseln können, kann ein Header oder Path Param ein Input sein, aber keine Authority.

Der richtige Flow: Credential prüfen, Subject holen, allowed tenants/scopes holen, requested tenant mit der allowed list abgleichen, resolved tenant im Context anhängen. Wenn der Tenant nicht erlaubt ist, ist das 403, nicht 401.

Nutze x-tenant-id nicht als Source of Truth.
Cache Tenant Permissions nicht länger, als dein Revocation-Modell erlaubt.
Logge tenant id und subject id, aber nie das Credential.
Schreibe Tests für Cross-Tenant Access, nicht nur für missing token.

Tenant muss vom Server resolved und geprüft werden. Header oder Path Param kann die Anfrage des Nutzers sein, aber kein Beweis für Zugriff.

Screenshot des Abschnitts multi-tenant-context

Falsche Auth Errors erzeugen Probleme für Clients, Logs und Security Review. In einer Bun Pipeline sollte der Contract früh festgelegt werden.

01

Credential fehlt oder ist ungültig

Kein Authorization, malformed token, invalid signature, session expired, API key nicht gefunden. Der Client muss verstehen, dass Authentication nötig ist.

02

Credential ist gültig, aber die Aktion ist verboten

Subject ist authenticated, hat aber keinen Tenant Access, Scope, Role oder Permission für die Ressource.

03

Auth Abuse oder Rate Limit

Brute Force, zu viele invalid token attempts, API key abuse. Vermische das nicht mit 401, weil Client und Monitoring anders reagieren müssen.

04

Auth Infrastructure Failure

Session Store, JWKS Endpoint, Redis oder DB ist nicht verfügbar. Für manche Routes ist fail closed besser; für public degraded flows kann eine andere Policy nötig sein.

Kurz gesagt

Ein einheitliches Error Format ist genauso wichtig wie der richtige Status Code. Client, Monitoring und Security Tooling müssen einen stabilen Contract sehen.

Auth wird oft zur schwersten Middleware, weil Crypto, Storage, Tenant Resolution und Audit zusammenkommen. Optimierung beginnt nicht beim Algorithmus, sondern bei Routing und Caching Policy.

Gut: public/system routes außerhalb der Auth Pipeline

/health, /ready, static assets und public docs sollten kein Token Parsing oder Session Lookup machen.

Vorsicht: DB Lookup für jedes JWT

Wenn jedes JWT trotzdem zur Verification in die DB geht, frage dich, ob JWT dir gegenüber einer Session ID überhaupt einen Vorteil gibt. Vielleicht brauchst du ein Session-/Introspection-Modell.

Gut: kurzer Cache für stabile Auth Metadata

Tenant Membership, API Key Owner und JWKS Keys können mit klarer TTL und Revocation Story gecacht werden.

Vorsicht: langlebiger Permissions Cache

Permissions ändern sich. Wenn der Cache länger lebt als die Security Expectation, behält ein Nutzer nach Revoke weiterhin Zugriff.

Kurz gesagt

Auth Performance darf nicht mit Revocation kollidieren. Wenn du cachst, definiere sofort TTL, Invalidation und High-Risk Fallback.

Diese Fehler sind nicht nur Bun-spezifisch, aber in Bun-Projekten tauchen sie oft als „wir haben nur schnell eine thin middleware geschrieben“ auf.

jwt.decode() verwenden oder Payload ohne Signature Verification lesen.

exp, iss, aud und Algorithmus bei JWT nicht prüfen.

Access Token in localStorage für eine Browser App speichern, ohne klare XSS Threat Model.

Authorization, Cookies, Refresh Token oder vollständigen API Key loggen.

API Keys in Plaintext statt hash + prefix lookup speichern.

API Key ohne Scopes, Owner, Environment und Rotation Policy ausgeben.

x-tenant-id als autoritative Quelle für Tenant Context behandeln.

200 mit { error: ... } für Auth Failures zurückgeben.

Authentication, Tenant Membership und Resource Authorization in eine globale Middleware mischen.

Review-Regel

Wenn Middleware nicht als kleine State Machine mit 401/403/next erklärbar ist, ist sie schon zu komplex oder übernimmt Verantwortung für die falsche Schicht.

Vor Staging oder Security Review lohnt sich diese Liste. Sie ist bewusst als Engineering Checklist formuliert, nicht als generischer Rat.

Credential Extraction passiert einmal

Eine Schicht liest Authorization/cookies/API key und gibt das Ergebnis als typed context weiter.

JWT Verification ist vollständig

Signature, algorithm, expiry, issuer, audience, subject und clock skew policy werden geprüft.

Session Cookies sind geschützt

httpOnly, secure, sameSite, enger path, TTL und HTTPS policy sind definiert.

API Keys werden nicht offen gespeichert

In der Datenbank liegen nur hash, key prefix, owner, scopes, last used, created/revoked metadata.

Tenant Context wird geprüft

Requested tenant wird gegen membership/scopes des Subjects geprüft und nicht als Fakt aus einem Header übernommen.

401 und 403 sind getrennt

Missing/invalid credential ergibt 401; valid credential ohne permission ergibt 403.

Secrets sind redacted

Logs, Tracing, Error Reports und Analytics enthalten keine Tokens, Cookies, API Keys oder PII.

Revocation Story existiert

Für JWT, Sessions und API Keys gibt es ein klares Modell für Revocation, Rotation und forced logout.

In Bun ist es leicht, einen schnellen Auth Wrapper zu schreiben. Schwieriger ist Auth-Middleware, die Authentication und Authorization nicht vermischt, nicht zwischen Tenants leakt, keine Secrets loggt, keinen unnötigen DB Lookup bei jedem Request erzeugt und einen sauberen Error Contract hat.

JWT, Sessions und API Keys konkurrieren nicht als „besser“ und „schlechter“. Sie lösen unterschiedliche Aufgaben. JWT ist praktisch für stateless access, Sessions für Browser UX und kontrollierten Logout, API Keys für Integrationen. In Production braucht man oft Hybrid, aber mit einheitlichem Audit und Policy Layer.

Eine richtige Bun Auth Pipeline sieht simpel aus: extract, verify, resolve subject, resolve tenant, attach context, continue oder reject. Alles andere muss explizit designt, getestet und gemessen werden.

Ist JWT besser als Sessions in Bun.js?

Nicht immer. JWT ist nützlich für stateless access und Service-to-Service-Szenarien, aber Revocation ist schwieriger. Sessions passen besser zu Browser SaaS, wo kontrollierter Logout, Secure Cookies und ein Session Store nötig sind. Die Wahl hängt von Client, Threat Model und Revocation-Anforderungen ab. [4][5]

Kann man Auth-Middleware ohne Hono oder Elysia bauen?

Ja. Natives `Bun.serve` erlaubt Auth als Funktionskomposition rund um `Request`/`Response`. Aber du bist selbst verantwortlich für Context, Errors, Reihenfolge, Tests und Security Policy.

Was sollte Middleware zurückgeben: 401 oder 403?

`401` für missing/invalid credential: kein Token, session expired, invalid signature, API key nicht gefunden. `403` für ein gültiges Credential ohne Permission, Tenant Access oder required Scope.

Wo sollte Tenant Context gespeichert werden?

Im request-scoped Auth Context nach Prüfung von Credential und Membership. Vertraue `x-tenant-id` nicht als Source of Truth. Header oder Path Param kann der requested tenant sein, aber Middleware muss prüfen, dass das Subject Zugriff darauf hat.

Darf man Tokens zum Debuggen loggen?

Nein. Authorization Headers, Cookies, Refresh Tokens und API Keys sollten redacted werden. Logge request id, subject id, tenant id, auth method und error class, aber nicht das Credential.

Wie sollte man API Keys speichern?

Zeige den vollständigen API Key nur einmal bei der Erstellung, speichere einen Hash, halte einen kurzen Prefix für Lookup, und ergänze owner, scopes, environment, created/last used/revoked metadata sowie eine Rotation Policy.

Diese Quellen bestätigen das Verhalten der Bun Cookie API, Hono/Elysia Auth Middleware/Plugins und die Security Baseline für JWT und Session Management.

Geprüft: 14. Mai 2026Gilt für: Bun 1.3.xGilt für: Bun.serve routesGilt für: Hono 4.xGilt für: Elysia 1.xGilt für: TypeScript APIGetestet mit: Bun CookieMapGetestet mit: Hono JWT Auth MiddlewareGetestet mit: Hono Bearer Auth MiddlewareGetestet mit: Elysia JWT pluginGetestet mit: Elysia Bearer plugin

PAS7 Studio kann helfen, Auth-Middleware für Bun, Hono oder Elysia zu designen: JWT-/Session-/API-Key-Modell, Tenant Context, Scopes, Secure Cookies, Rotation, Observability und Security Review.

Das ist besonders nützlich für SaaS, Internal Platforms, B2B APIs und Migrationen von Express/Fastify, bei denen Auth Behavior bereits über Middleware, Guards und Helpers verteilt ist.

Sie sind hier02/05

Auth Middleware in Bun.js: JWT, Sessions, API Keys und Multi-Tenant Context

Verwandte Artikel

ai-assistants

AI Assistant Entwicklung Kosten 2026: RAG, Knowledge Base, Integrationen und Support

Praktischer Leitfaden zu Kosten fuer AI Assistants: RAG, Knowledge Base, Channels, Tool Use, Guardrails, Evaluations, Monitoring und Support.

blogs

KI fur Landingpage-Entwicklung: wo sie Launches beschleunigt und wo sie Conversion schadet

Eine praxisnahe Analyse zur Nutzung von KI fur Landingpages: v0, Webflow AI, Builder.io, Framer-ahnliche Builder, UX-Generierung, Copy, SEO, Personalisierung, A/B-Tests, Template-Risiken, Accessibility, Security und technischer Schuldenaufbau.

growth

AI SEO / GEO im Jahr 2026: Ihre nächsten Kunden sind nicht Menschen — sondern Agents

Suche verschiebt sich von Klicks zu Antworten. Bots und AI-Agents crawlen, zitieren, empfehlen — und kaufen zunehmend. Erfahren Sie, was AI SEO / GEO bedeutet, warum klassisches SEO nicht mehr reicht und wie PAS7 Studio Marken im agentischen Web sichtbar macht.

blogs

Der leistungsstärkste Chip von Apple? M5 Pro und M5 Max brechen Rekorde

Eine Analyse zu Apple M5 Pro und M5 Max im März 2026. Wir zeigen, warum diese Chips als die stärksten professionellen Laptop-SoCs von Apple gelten können, wie sie sich gegen M4 Pro, M4 Max, M1 Pro, M1 Max schlagen und was der Vergleich mit aktuellen Intel- und AMD-Chips zeigt.

Professionelle Entwicklung für Ihr Geschäft

Wir erstellen moderne Web-Lösungen und Bots für Unternehmen. Erfahren Sie, wie wir Ihnen helfen können, Ihre Ziele zu erreichen.