buzzster
v1.0.4
Published
Buzzster Client - Express middleware to protect routes with agent authentication
Downloads
13
Maintainers
Readme
Buzzster Client
Express middleware to protect your routes with agent authentication.
What It Does
- Blocks browsers (User-Agent detection)
- Verifies tokens with central Buzzster API
- Caches verification locally (30s default) to reduce API calls
- Attaches agent info to req.agent
- Returns helpful error messages
Installation
npm install buzzster-clientQuick Start
const express = require('express');
const Buzzster = require('buzzster-client');
const app = express();
// Create middleware
const buzzster = new Buzzster({
apiUrl: 'https://api.buzzster.xyz', // Central API
blockBrowsers: true,
enforceAuthentication: true
});
// Apply to all routes
app.use(buzzster);
// Now only agents can access
app.get('/api/secret', (req, res) => {
res.json({
message: 'Hello, ' + req.agent.name,
agentId: req.agent.id
});
});
app.listen(8080);Configuration Options
const buzzster = new Buzzster({
// Required
apiUrl: 'https://api.buzzster.xyz',
// Optional
blockBrowsers: true, // Block User-Agent that look like browsers
enforceAuthentication: true, // Require X-Bio-Token header
cacheTokens: true, // Cache verification results locally
cacheTTL: 30000 // Cache time-to-live (ms)
});How It Works
Layer 1: Passive Filtering (Local)
User-Agent: Mozilla/5.0 ... → 406 Not Acceptable
Accept: text/html → 406 Not Acceptable
Accept-Language: en-US → 406 Not AcceptableLayer 2: Token Verification (Central API)
POST /verify on central API
{
"agentId": "agent_xyz",
"token": "eyJhbGc..."
}
Response:
{
"valid": true,
"agent": {
"id": "agent_xyz",
"name": "MyAgent",
"version": "1.0.0"
}
}Layer 3: Cache (Local)
Result cached for 30 seconds
Reduces API calls during request burstUsage Examples
Protect Specific Routes
const express = require('express');
const Buzzster = require('buzzster-client');
const app = express();
const publicRoutes = require('./routes/public');
const agentOnlyRoutes = require('./routes/agent-only');
// Public routes (no auth)
app.use('/public', publicRoutes);
// Apply Buzzster middleware
const buzzster = new Buzzster('https://api.buzzster.xyz');
app.use('/api', buzzster, agentOnlyRoutes);
app.listen(8080);Custom Error Handling
const buzzster = new Buzzster('https://api.buzzster.xyz');
app.use((req, res, next) => {
buzzster(req, res, (err) => {
if (err) {
// Custom error handling
console.error('Auth error:', err);
res.status(401).json({
success: false,
message: 'Custom error message'
});
} else {
next();
}
});
});Access Agent Information
app.get('/api/profile', (req, res) => {
// req.agent is populated by middleware
res.json({
you: req.agent.name,
agentId: req.agent.id,
version: req.agent.version,
permissions: req.agent.permissions
});
});Request Headers Required
Agents must send:
X-Bio-Agent-Id: agent_a1b2c3d4e5f6
X-Bio-Token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
User-Agent: MyAgent/1.0
Accept: application/jsonDo NOT send:
Accept: text/html
Accept-Language: en-USResponse Headers
Middleware adds:
X-Bio-Verified: true
X-Bio-Agent-Name: MyAgent
X-Bio-Version: 3.0Error Responses
406 Not Acceptable (Browser Detected)
{
"error": "BIOLOGICAL_ENTITY_DETECTED",
"message": "This resource is reserved for automated agents",
"tip": "Use an API client. Ensure User-Agent does not look like a browser"
}428 Precondition Required (Auth Missing)
{
"error": "AUTHENTICATION_REQUIRED",
"message": "Valid agent token required to access this resource",
"protocol": {
"headers": {
"X-Bio-Agent-Id": "Your agent ID",
"X-Bio-Token": "JWT token"
}
}
}401 Unauthorized (Invalid Token)
{
"error": "INVALID_TOKEN",
"message": "Token signature is invalid"
}403 Forbidden (Agent Revoked)
{
"error": "AGENT_NOT_ACTIVE",
"message": "Agent status is revoked"
}Token Caching
By default, token verification results are cached for 30 seconds:
// This prevents hammering the central API
// during request bursts
// Clear all cache
buzzster.clearCache();
// Clear specific token
buzzster.clearCacheEntry(agentId, token);Performance Notes
- Local validation: User-Agent check (instant, no API call)
- First request: API call to central Buzzster server (~5-50ms)
- Cached requests: Served from local cache (<1ms)
- Cache hit rate: ~95% for typical agents
Testing
// Mock requests
const request = require('supertest');
const app = require('./app');
describe('Protected endpoint', () => {
it('should reject browsers', async () => {
const res = await request(app)
.get('/api/secret')
.set('User-Agent', 'Mozilla/5.0 Chrome/...');
expect(res.status).toBe(406);
});
it('should reject missing auth', async () => {
const res = await request(app)
.get('/api/secret')
.set('User-Agent', 'MyBot/1.0');
expect(res.status).toBe(428);
});
it('should allow valid agents', async () => {
const res = await request(app)
.get('/api/secret')
.set('User-Agent', 'MyBot/1.0')
.set('X-Bio-Agent-Id', 'agent_xyz')
.set('X-Bio-Token', 'valid_token...');
expect(res.status).toBe(200);
expect(res.body.agent.id).toBe('agent_xyz');
});
});Troubleshooting
"Cannot connect to central API"
// Check API URL
const buzzster = new Buzzster('https://api.buzzster.xyz');
// Verify API is running
curl https://api.buzzster.xyz/health"Token always invalid"
// Regenerate token (expires after 1 hour)
const newToken = crypto.createToken(privateKey, agentId, metadata, 3600);
// Use new token in X-Bio-Token header"Agents keep getting 406"
// Check headers
curl -v \
-H "User-Agent: MyBot/1.0" \
-H "Accept: application/json" \
-H "X-Bio-Agent-Id: agent_xyz" \
-H "X-Bio-Token: ..." \
http://localhost:8080/api/secret
# Do NOT include:
# - "Mozilla" in User-Agent
# - "text/html" in Accept
# - "Accept-Language" headerLicense
MIT
Support
- 📖 SKILL.md — Full developer guide
- 🏗️ ARCHITECTURE.md — System design
- 🛡️ buzzster-api — Central API server
- 🔗 GitHub: https://github.com/openclaw/buzzster
