Stop shipping AI integrations with shared API keys and no audit trail
Reference implementation · Live demo in ChatGPT · gatewaystack.com
AI apps have three actors — user, LLM, and backend — but no shared identity layer. The user authenticates with the LLM, then the LLM calls your backend with a shared API key. Your backend can't tell who the request is for.
Without GatewayStack With GatewayStack
USER (Alice) USER (Alice)
│ │
│ ✓ Authenticated │ ✓ Authenticated
▼ ▼
LLM LLM
│ │
│ ❌ Shared API key │ ✓ RS256 JWT
▼ ▼
BACKEND GATEWAYSTACK
│ (Verify & Inject)
│ ❓ Who is this? │
│ ❓ What can they do? │ ✓ X-User-Id, scopes
▼
BACKEND
│
│ ✅ Knows: Alice, scopes
│ ✅ Enforces policy
GatewayStack sits between the LLM and your backend. It verifies OAuth tokens, enforces per-user policies, and injects verified identity — so every AI request is attributable, authorized, and auditable. Full explanation →
npm install @gatewaystack/identifiabl expressimport express from "express";
import { identifiabl } from "@gatewaystack/identifiabl";
const app = express();
app.use(identifiabl({
issuer: process.env.OAUTH_ISSUER!,
audience: process.env.OAUTH_AUDIENCE!,
}));
app.get("/api/me", (req, res) => {
res.json({ user: req.user.sub, scopes: req.user.scope });
});
app.listen(8080);Every request now requires a valid RS256 JWT. req.user contains the verified identity.
All six governance layers are live on npm. Each has a -core package (framework-agnostic) and an Express middleware wrapper. Detailed breakdown →
Wire all six layers together. Each is optional — use only what you need.
npm install @gatewaystack/identifiabl @gatewaystack/transformabl @gatewaystack/validatabl \
@gatewaystack/limitabl @gatewaystack/proxyabl @gatewaystack/explicabl @gatewaystack/request-context expressimport express from "express";
import { runWithGatewayContext } from "@gatewaystack/request-context";
import { identifiabl } from "@gatewaystack/identifiabl";
import { transformabl } from "@gatewaystack/transformabl";
import { validatabl } from "@gatewaystack/validatabl";
import { limitabl } from "@gatewaystack/limitabl";
import { createProxyablRouter, configFromEnv } from "@gatewaystack/proxyabl";
import { createConsoleLogger, explicablLoggingMiddleware } from "@gatewaystack/explicabl";
const app = express();
app.use(express.json());
// 1. Establish request context for downstream layers
app.use((req, _res, next) => {
runWithGatewayContext(
{ request: { method: req.method, path: req.path } },
() => next()
);
});
// 2. Log every request
app.use(explicablLoggingMiddleware(createConsoleLogger()));
// 3. Require verified RS256 token
app.use(identifiabl({
issuer: process.env.OAUTH_ISSUER!,
audience: process.env.OAUTH_AUDIENCE!,
}));
// 4. Detect PII and classify content safety
app.use("/tools", transformabl({ blockThreshold: 80 }));
// 5. Enforce authorization policies
app.use("/tools", validatabl({
requiredPermissions: ["tool:read"],
}));
// 6. Apply rate limits and budget caps
app.use("/tools", limitabl({
rateLimit: { windowMs: 60_000, maxRequests: 100 },
budget: { maxSpend: 500, periodMs: 86_400_000 },
}));
// 7. Route /tools to your tool/model backends
app.use("/tools", createProxyablRouter(configFromEnv(process.env)));
app.listen(8080, () => {
console.log("GatewayStack running on :8080");
});Or clone and run the reference gateway directly:
git clone https://github.com/davidcrowe/GatewayStack
cd GatewayStack
npm install
npm run dev # gateway on :8080, admin UI on :5173| Feature | Kong / Apigee / AWS API Gateway | GatewayStack |
|---|---|---|
| JWT validation | Built-in | Built-in |
| Rate limiting | Built-in | Built-in |
| Path/method routing | Built-in | Built-in |
| User identity normalization | Manual (custom plugin) | Built-in |
| Three-party identity binding (LLM → backend) | Manual (custom logic) | Built-in |
| Per-tool scope enforcement | Manual (custom policy) | Built-in |
| PII detection & redaction | Not available | Built-in |
| Content safety classification | Not available | Built-in |
| Pre-flight budget checks | Manual (custom plugin) | Built-in |
| Agent runaway prevention | Not available | Built-in |
| Apps SDK / MCP compliance | Manual (PRM endpoint) | Built-in |
| AI audit trails | Manual (log forwarding) | Built-in |
| Path | Description |
|---|---|
packages/ |
Six -core packages (framework-agnostic) + six Express middleware wrappers, plus request-context, compat, and integrations |
apps/gateway-server |
Express reference server wiring all six layers, /protected/* samples, Docker image |
apps/admin-ui |
Vite/React dashboard that polls /health |
demos/ |
MCP issuer + ChatGPT Apps SDK connectors that mint demo JWTs |
tools/ |
Echo server, mock tool backend, Cloud Run deploy helper |
tests/ |
Vitest smoke tests |
docs/ |
Auth0 walkthroughs, conformance output, endpoint references, troubleshooting |
npm test135 tests across 17 test files covering all five core packages.
- Node.js 20+
- npm 10+ (or pnpm 9)
- An OIDC provider issuing RS256 access tokens (Auth0, Okta, Entra ID, Keycloak, etc.)
- The Three-Party Problem
- Package Breakdown
- Examples
- Demos
- Environment & Health Endpoints
- Deployment
- Troubleshooting
- Production Checklist
- Run the tests:
npm test - Read
CONTRIBUTING.md - Report issues on GitHub Issues
For the enterprise and leadership pitch, see gatewaystack.com.
