Authentication Guide
How Phlow handles A2A Protocol authentication.
How It Works
sequenceDiagram
participant A as Agent A
participant B as Agent B
participant S as Supabase
A->>A: Sign JWT with private key
A->>B: Request + JWT + Agent ID
B->>S: Lookup Agent A's public key
S->>B: Return agent card
B->>B: Verify JWT signature
B->>A: Authenticated response
Making Authenticated Requests
As a Client
// 1. Create a signed JWT
const token = await phlow.createToken({
targetAgent: 'agent-b-id',
permissions: ['read', 'write']
});
// 2. Make the request
const response = await fetch('https://agent-b.com/api/data', {
headers: {
'Authorization': `Bearer ${token}`,
'X-Phlow-Agent-Id': 'agent-a-id'
}
});
As a Server
// Phlow handles all verification automatically
app.post('/api/data', phlow.authenticate(), (req, res) => {
// req.phlow contains verified agent info
console.log('Request from:', req.phlow.agent.name);
console.log('Permissions:', req.phlow.claims.permissions);
res.json({ data: 'secure data' });
});
JWT Token Structure
Phlow uses A2A-compliant JWT tokens:
{
"sub": "target-agent-id", // Who can use this token
"iss": "source-agent-id", // Who created this token
"aud": "target-agent-id", // Intended recipient
"exp": 1234567890, // Expiration time
"iat": 1234567890, // Issued at time
"permissions": ["read"], // Granted permissions
"metadata": {} // Additional data
}
Permission Checking
Basic Check
app.post('/api/write',
phlow.authenticate({ requiredPermissions: ['write'] }),
handler
);
Manual Check
app.post('/api/data', phlow.authenticate(), (req, res) => {
const hasPermission = req.phlow.claims.permissions.includes('write');
if (!hasPermission) {
return res.status(403).json({ error: 'Insufficient permissions' });
}
// Process request
});
Token Lifecycle
Token Generation
// Tokens are auto-generated when calling other agents
const response = await phlow.callAgent(url, data);
// Phlow creates and attaches the token automatically
Token Expiry
- Default: 1 hour
- Configurable via
tokenExpiry
option - Automatic refresh before expiry
Token Refresh
// Check if token needs refresh
if (await phlow.checkTokenRefresh(token)) {
// Get new token
const newToken = await phlow.refreshToken(token);
}
Error Handling
Common authentication errors:
try {
await phlow.authenticate()(req, res, next);
} catch (error) {
if (error.code === 'AGENT_NOT_FOUND') {
// Agent not registered in Supabase
} else if (error.code === 'TOKEN_EXPIRED') {
// JWT has expired
} else if (error.code === 'INVALID_SIGNATURE') {
// JWT signature doesn't match
}
}
Audit Trail
With audit logging enabled, Phlow tracks:
- Successful authentications
- Failed authentication attempts
- Permission denials
- Rate limit violations
View in Supabase:
SELECT * FROM auth_audit_log
WHERE agent_id = 'agent-a-id'
ORDER BY timestamp DESC;
Next Steps
- Making Agent Calls - Call other agents
- Security Best Practices - Secure your implementation
- Troubleshooting - Common auth issues