@agent-id/express
v0.1.2
Published
AgentID verifier middleware for Express.js — blocks unauthorized AI agents from your API routes
Readme
@agent-id/express
Express.js middleware that automatically detects AI-agent traffic and requires a valid AgentID JWT. Human browser traffic always passes through untouched.
Install
npm install @agent-id/expressRequires express >= 4 and node >= 18.
Setup — 2 steps
1. Add the middleware
import express from 'express';
import { agentID } from '@agent-id/express';
const app = express();
app.use(agentID());
app.listen(3000);That's it. The middleware now:
- Lets all human browser traffic through unchanged
- Requires a valid AgentID JWT from any AI agent / bot
- Returns
403 AGENT_UNAUTHORIZEDwhen the JWT is missing or invalid
2. Read the verified identity in your route handlers (optional)
app.get('/api/data', (req, res) => {
const agent = req.agentId;
if (agent?.verified) {
// Verified AI agent — claims are fully typed
console.log(agent.claims.sub); // pseudonymous stable user ID
console.log(agent.claims.auth_method); // "bankid"
return res.json({ ok: true, sub: agent.claims.sub });
}
// Human traffic: agent.reason === 'not_agent'
return res.json({ ok: true });
});req.agentId is typed automatically — no extra TypeScript configuration needed.
How agents authenticate
Agents add one header to every request:
Authorization: Bearer <agentid-jwt>The JWT is obtained by completing a BankID flow at agentidapp.vercel.app. Tokens are valid for 1 hour.
Options
All options are optional — agentID() with no arguments works out of the box.
app.use(agentID({
// Return 403 when an agent has no valid token (default: true).
// Set to false to let unverified agents through (useful for logging / gradual rollout).
blockUnauthorizedAgents: true,
// Override the JWKS endpoint — only needed if you self-host AgentID.
jwksUrl: 'https://your-agentid.example.com/api/jwks',
// Clock skew tolerance in seconds (default: 30).
clockTolerance: 30,
// Fully custom response when an agent is rejected.
onUnauthorizedAgent: (req, res, next, reason) => {
res.status(403).json({ error: 'No AgentID token', reason });
},
}));What gets verified
Verification is fully offline after the first request. The public key is fetched once from the AgentID JWKS endpoint and cached for 1 hour — no per-request network call.
| Check | Requirement |
|---|---|
| Signature | RS256 — alg:none and HS256 are explicitly rejected |
| Issuer (iss) | Must equal "agentid" |
| Expiry (exp) | Must be in the future |
| auth_method | Must equal "bankid" |
JWT claims
| Field | Description |
|---|---|
| sub | Pseudonymous stable user ID (HMAC-SHA256 of BankID personal number — non-reversible, same person always gets the same ID) |
| auth_method | Always "bankid" |
| iss | "agentid" |
| exp | Unix timestamp — 1 hour from issue |
| iat | Unix timestamp — when issued |
| jti | Unique token ID |
