-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture Security
dev-mondoshawan edited this page Apr 16, 2026
·
1 revision
**Referenced Files in This Document**
- [backend/src/services/bagsAuthVerifier.js](https://github.com/RunTimeAdmin/AgentID/blob/main/backend/src/services/bagsAuthVerifier.js)
- [backend/src/services/pkiChallenge.js](https://github.com/RunTimeAdmin/AgentID/blob/main/backend/src/services/pkiChallenge.js)
- [backend/src/middleware/rateLimit.js](https://github.com/RunTimeAdmin/AgentID/blob/main/backend/src/middleware/rateLimit.js)
- [backend/src/middleware/errorHandler.js](https://github.com/RunTimeAdmin/AgentID/blob/main/backend/src/middleware/errorHandler.js)
- [backend/src/models/queries.js](https://github.com/RunTimeAdmin/AgentID/blob/main/backend/src/models/queries.js)
- [backend/server.js](https://github.com/RunTimeAdmin/AgentID/blob/main/backend/server.js)
Loading
Loading
Loading
Loading
Loading
Loading
Loading
- Introduction
- Authentication Architecture
- Authorization Architecture
- Data Protection
- Rate Limiting Architecture
- Error Handling Security
AgentID's security architecture is built on cryptographic verification using Ed25519 signatures, with defense-in-depth through multiple layers of protection.
flowchart TD
Start(["Signature Verification"]) --> Decode["Base58 Decode"]
Decode --> Verify["tweetnacl.verify()"]
Verify -->|Valid| Success["Authentication Success"]
Verify -->|Invalid| Failure["Authentication Failure"]
Decode -->|Invalid Format| Failure
sequenceDiagram
participant Client as "Client"
participant Route as "Route Handler"
participant Service as "Auth Service"
participant Crypto as "Crypto Module"
participant DB as "Database"
Client->>Route: Request with signature
Route->>Service: verifySignature()
Service->>Crypto: decode inputs
Crypto-->>Service: decoded bytes
Service->>Crypto: verify Ed25519
Crypto-->>Service: boolean result
Service->>DB: verify nonce not used
DB-->>Service: nonce status
Service-->>Route: auth result
Route-->>Client: response
flowchart TD
Issue["Issue Challenge"] --> GenNonce["Generate UUID"]
GenNonce --> BuildMsg["Build Message:<br/>AGENTID-VERIFY:{pubkey}:{nonce}:{timestamp}"]
BuildMsg --> Store["Store with Expiry"]
Store --> Encode["Base58 Encode"]
Encode --> Return["Return to Client"]
Verify["Verify Response"] --> Load["Load Challenge"]
Load --> CheckExpiry["Check Expiry"]
CheckExpiry --> CheckUsed["Check Not Used"]
CheckUsed --> VerifySig["Verify Signature"]
VerifySig --> MarkUsed["Mark Used"]
MarkUsed --> UpdateTS["Update Timestamp"]
UpdateTS --> ReturnSuccess["Return Success"]
CheckExpiry -->|Expired| Error["Error: Expired"]
CheckUsed -->|Used| Error
VerifySig -->|Invalid| Error
| Action | Authorization Method |
|---|---|
| Read agent data | Public |
| Register agent | Ed25519 signature |
| Update agent | Ed25519 signature |
| Verify challenge | Ed25519 signature |
| Flag agent | Ed25519 signature + reporter signature |
// Registration requires:
{
pubkey, // Agent's public key
signature, // Ed25519 signature of message
message, // Challenge message
nonce // Challenge nonce
}
// Flagging requires:
{
reason, // Flag reason
reporterPubkey, // Reporter's public key
signature, // Reporter's Ed25519 signature
timestamp // Timestamp for freshness
}flowchart LR
Input["User Input"] --> Validate["Input Validation"]
Validate --> ParamQuery["Parameterized Query"]
ParamQuery --> DB[("PostgreSQL")]
Validate -->|Invalid| Reject["Reject Request"]
All database queries use parameterized statements:
// Safe
await query('SELECT * FROM agents WHERE pubkey = $1', [pubkey]);
// Never do this
await query(`SELECT * FROM agents WHERE pubkey = '${pubkey}'`);Output encoding for dynamic content:
function escapeHtml(text) {
const map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
return text.replace(/[&<>"']/g, m => map[m]);
}graph TB
Public["Public Endpoints<br/>100 req/15min"] --> Default
Auth["Auth Endpoints<br/>10 req/15min"] --> Strict
Strict["Strict Endpoints<br/>5 req/15min"]
// Default rate limiter
const defaultLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
message: 'Too many requests'
});
// Strict rate limiter for auth
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 10,
message: 'Too many authentication attempts'
});
// Apply to routes
app.use('/api/', defaultLimiter);
app.use('/api/register', authLimiter);flowchart TD
Error["Error Occurs"] --> Log["Log Full Error<br/>(Server-side)"]
Log --> CheckEnv{"Environment?"}
CheckEnv -->|Development| DevResponse["Return Detailed Error"]
CheckEnv -->|Production| ProdResponse["Return Generic Error"]
Helmet.js provides:
| Header | Purpose |
|---|---|
| Content-Security-Policy | XSS protection |
| X-Frame-Options | Clickjacking protection |
| X-Content-Type-Options | MIME sniffing protection |
| Strict-Transport-Security | HTTPS enforcement |
| X-DNS-Prefetch-Control | DNS prefetch control |
flowchart LR
Secrets["Secrets"] --> Env["Environment Variables"]
Env --> App["Application"]
Secrets -->|Production| Vault["Secrets Manager"]
Vault --> App
Best practices:
- Never commit secrets to version control
- Use different keys for different environments
- Rotate keys regularly
- Use secrets manager in production