API Reference
This page documents the complete API for all Phlow packages. Use the tabs below to navigate between different language implementations.
PhlowMiddleware
The main middleware class for Phlow authentication.
class PhlowMiddleware {
constructor(config: PhlowConfig)
authenticate(options?: VerifyOptions): MiddlewareFunction
refreshTokenIfNeeded(): MiddlewareFunction
getSupabaseClient(): SupabaseClient
getAgentCard(): AgentCard
}
Constructor
new PhlowMiddleware(config: PhlowConfig)
Parameters:
- config
: Configuration object containing Supabase credentials, agent card, and options
Example:
const phlow = new PhlowMiddleware({
supabaseUrl: 'https://your-project.supabase.co',
supabaseAnonKey: 'your-anon-key',
agentCard: {
agentId: 'my-agent',
name: 'My Agent',
permissions: ['read:data'],
publicKey: 'RSA public key',
},
privateKey: 'RSA private key',
options: {
enableAudit: true,
rateLimiting: {
maxRequests: 100,
windowMs: 60000,
},
},
});
authenticate()
Creates Express middleware for authentication.
authenticate(options?: VerifyOptions): MiddlewareFunction
Parameters:
- options.requiredPermissions?
: Array of required permissions
- options.allowExpired?
: Whether to allow expired tokens
Example:
// Basic authentication
app.get('/protected', phlow.authenticate(), handler);
// Require specific permissions
app.get('/admin', phlow.authenticate({
requiredPermissions: ['admin:users']
}), handler);
// Allow expired tokens
app.get('/refresh', phlow.authenticate({
allowExpired: true
}), handler);
refreshTokenIfNeeded()
Middleware to check if tokens need refreshing.
refreshTokenIfNeeded(): MiddlewareFunction
Example:
app.use(phlow.refreshTokenIfNeeded());
JWT Utilities
generateToken()
Generate a JWT token for agent authentication.
function generateToken(
agentCard: AgentCard,
privateKey: string,
audience: string,
expiresIn?: string
): string
Parameters:
- agentCard
: The agent card containing agent information
- privateKey
: Private key to sign the token
- audience
: Target agent ID
- expiresIn
: Token expiration (default: '1h')
Example:
import { generateToken } from 'phlow-auth';
const token = generateToken(
myAgentCard,
myPrivateKey,
'target-agent-id',
'2h'
);
verifyToken()
Verify a JWT token.
function verifyToken(
token: string,
publicKey: string,
options?: {
audience?: string;
issuer?: string;
ignoreExpiration?: boolean;
}
): JWTClaims
Parameters:
- token
: JWT token to verify
- publicKey
: Public key to verify signature
- options
: Verification options
Example:
import { verifyToken } from 'phlow-auth';
const claims = verifyToken(
token,
senderPublicKey,
{
audience: 'my-agent-id',
issuer: 'sender-agent-id',
}
);
decodeToken()
Decode a JWT token without verification.
function decodeToken(token: string): JWTClaims | null
isTokenExpired()
Check if a token is expired.
function isTokenExpired(token: string, thresholdSeconds?: number): boolean
SupabaseHelpers
Helper class for Supabase operations.
class SupabaseHelpers {
constructor(supabase: SupabaseClient)
async registerAgentCard(agentCard: AgentCard): Promise<void>
async getAgentCard(agentId: string): Promise<AgentCard | null>
async listAgentCards(filters?: {
permissions?: string[];
metadata?: Record<string, any>;
}): Promise<AgentCard[]>
static generateRLSPolicy(tableName: string, policyName: string): string
static generateAgentSpecificRLSPolicy(
tableName: string,
policyName: string,
agentIdColumn?: string
): string
static generatePermissionBasedRLSPolicy(
tableName: string,
policyName: string,
requiredPermission: string
): string
}
Example:
import { SupabaseHelpers } from 'phlow-auth';
const helpers = new SupabaseHelpers(supabaseClient);
// Register agent
await helpers.registerAgentCard(agentCard);
// Get agent
const agent = await helpers.getAgentCard('agent-id');
// List agents with permissions
const agents = await helpers.listAgentCards({
permissions: ['read:data'],
metadata: { environment: 'production' },
});
Types
AgentCard
interface AgentCard {
agentId: string;
name: string;
description?: string;
permissions: string[];
publicKey: string;
endpoints?: {
auth?: string;
api?: string;
};
metadata?: Record<string, any>;
}
PhlowConfig
interface PhlowConfig {
supabaseUrl: string;
supabaseAnonKey: string;
agentCard: AgentCard;
privateKey: string;
options?: {
tokenExpiry?: string;
refreshThreshold?: number;
enableAudit?: boolean;
rateLimiting?: {
maxRequests: number;
windowMs: number;
};
};
}
JWTClaims
interface JWTClaims {
sub: string; // Subject (agent ID)
iss: string; // Issuer (agent ID)
aud: string; // Audience (target agent ID)
exp: number; // Expiration time
iat: number; // Issued at time
permissions: string[];
metadata?: Record<string, any>;
}
PhlowContext
interface PhlowContext {
agent: AgentCard;
token: string;
claims: JWTClaims;
supabase: SupabaseClient;
}
Exceptions
class PhlowError extends Error {
constructor(message: string, code: string, statusCode?: number)
}
class AuthenticationError extends PhlowError {}
class AuthorizationError extends PhlowError {}
class ConfigurationError extends PhlowError {}
class TokenError extends PhlowError {}
class RateLimitError extends PhlowError {}
PhlowMiddleware
class PhlowMiddleware:
def __init__(self, config: PhlowConfig)
async def authenticate(
self,
token: str,
agent_id: str,
options: Optional[VerifyOptions] = None
) -> PhlowContext
def authenticate_sync(
self,
token: str,
agent_id: str,
options: Optional[VerifyOptions] = None
) -> PhlowContext
async def check_token_refresh(self, token: str) -> bool
def get_supabase_client(self) -> Client
def get_agent_card(self) -> AgentCard
Example:
from phlow_auth import PhlowMiddleware, PhlowConfig, AgentCard
config = PhlowConfig(
supabase_url="https://your-project.supabase.co",
supabase_anon_key="your-anon-key",
agent_card=AgentCard(
agent_id="my-agent",
name="My Agent",
permissions=["read:data"],
public_key="RSA public key",
),
private_key="RSA private key",
enable_audit=True,
)
phlow = PhlowMiddleware(config)
# Authenticate request
context = await phlow.authenticate(token, agent_id)
JWT Utilities
def generate_token(
agent_card: AgentCard,
private_key: str,
audience: str,
expires_in: str = "1h"
) -> str
def verify_token(
token: str,
public_key: str,
audience: Optional[str] = None,
issuer: Optional[str] = None,
ignore_expiration: bool = False
) -> JWTClaims
def decode_token(token: str) -> Optional[JWTClaims]
def is_token_expired(token: str, threshold_seconds: int = 0) -> bool
SupabaseHelpers
class SupabaseHelpers:
def __init__(self, supabase_client: Client)
async def register_agent_card(self, agent_card: AgentCard) -> None
def register_agent_card_sync(self, agent_card: AgentCard) -> None
async def get_agent_card(self, agent_id: str) -> Optional[AgentCard]
def get_agent_card_sync(self, agent_id: str) -> Optional[AgentCard]
async def list_agent_cards(
self,
permissions: Optional[List[str]] = None,
metadata_filters: Optional[Dict[str, Any]] = None
) -> List[AgentCard]
@staticmethod
def generate_rls_policy(table_name: str, policy_name: str) -> str
@staticmethod
def generate_agent_specific_rls_policy(
table_name: str,
policy_name: str,
agent_id_column: str = "agent_id"
) -> str
@staticmethod
def generate_permission_based_rls_policy(
table_name: str,
policy_name: str,
required_permission: str
) -> str
FastAPI Integration
from phlow_auth.integrations.fastapi import create_phlow_dependency
from fastapi import FastAPI, Depends
app = FastAPI()
# Create auth dependency
auth_required = create_phlow_dependency(phlow)
admin_required = create_phlow_dependency(
phlow,
required_permissions=["admin:users"]
)
@app.get("/protected")
async def protected_endpoint(context = Depends(auth_required)):
return {"agent": context.agent.name}
@app.get("/admin")
async def admin_endpoint(context = Depends(admin_required)):
return {"message": "Admin access granted"}
Types
AgentCard
class AgentCard(BaseModel):
agent_id: str
name: str
description: Optional[str] = None
permissions: List[str] = []
public_key: str
endpoints: Optional[Dict[str, str]] = None
metadata: Optional[Dict[str, Any]] = None
PhlowConfig
class PhlowConfig(BaseModel):
supabase_url: str
supabase_anon_key: str
agent_card: AgentCard
private_key: str
token_expiry: str = "1h"
refresh_threshold: int = 300
enable_audit: bool = False
rate_limiting: Optional[Dict[str, int]] = None
JWTClaims
class JWTClaims(BaseModel):
sub: str
iss: str
aud: str
exp: int
iat: int
permissions: List[str] = []
metadata: Optional[Dict[str, Any]] = None
Exceptions
class PhlowError(Exception):
def __init__(self, message: str, code: str = "PHLOW_ERROR", status_code: int = 500)
class AuthenticationError(PhlowError): pass
class AuthorizationError(PhlowError): pass
class ConfigurationError(PhlowError): pass
class TokenError(PhlowError): pass
class RateLimitError(PhlowError): pass
phlow init
Initialize a new Phlow project.
phlow init [options]
Options:
- -f, --force
- Overwrite existing configuration
Interactive prompts: - Supabase URL - Supabase anon key - Agent ID - Agent name - Agent description - Permissions - Generate new RSA key pair
phlow generate-card
Generate and register agent card.
phlow generate-card [options]
Options:
- -o, --output <file>
- Output file for agent card JSON
- --no-register
- Don't register with Supabase
phlow dev-start
Start local development environment.
phlow dev-start [options]
Options:
- -p, --port <port>
- Port for development server (default: 3000)
- -d, --dir <directory>
- Directory to create dev project (default: ./phlow-dev-agent)
phlow test-token
Generate test tokens for authentication.
phlow test-token [options] [token]
Options:
- -t, --target <agentId>
- Target agent ID (default: test-agent)
- -e, --expires <duration>
- Token expiration (default: 1h)
- --decode
- Decode and display an existing token
Arguments:
- token
- Token to decode (when using --decode)
DevServer
Development server with mock Supabase and test scenarios.
import { DevServer } from 'phlow-dev';
const server = new DevServer({
port: 3000,
enableCors: true,
enableTestEndpoints: true,
mockAgents: [agentCard1, agentCard2],
});
// Initialize mock Supabase
server.initializeMockSupabase();
// Add Phlow middleware
server.addPhlowMiddleware(middleware, '/protected');
// Add custom routes
server.addCustomRoute('get', '/custom', handler);
// Start server
await server.start();
TestRunner
Run predefined test scenarios.
import { TestRunner, TEST_SCENARIOS } from 'phlow-dev';
const runner = new TestRunner();
// Run all scenarios
const results = await runner.runAllScenarios();
// Run specific scenario
const scenario = TEST_SCENARIOS.find(s => s.name === 'valid_jwt_authentication');
const result = await runner.runScenario(scenario);
MockSupabase
Mock Supabase client for testing.
import { createMockSupabase } from 'phlow-dev';
const mockSupabase = createMockSupabase({
agents: [agentCard1, agentCard2],
enableAuditLogs: true,
});
// Use like regular Supabase client
const result = await mockSupabase.from('agent_cards').select('*');
HTTP Headers
Request Headers
Required:
- Authorization: Bearer <jwt-token>
- JWT token for authentication
- X-Phlow-Agent-Id: <agent-id>
- Agent ID of the requesting agent
Optional:
- Content-Type: application/json
- For POST/PUT requests
Response Headers
Authentication:
- X-Phlow-Token-Refresh: true
- Indicates token should be refreshed
Errors:
- WWW-Authenticate: Bearer
- For 401 responses
Error Codes
Authentication Errors (401)
TOKEN_MISSING
- No token providedTOKEN_INVALID
- Invalid token format or signatureTOKEN_EXPIRED
- Token has expiredAGENT_NOT_FOUND
- Agent not found in databaseAGENT_ID_MISSING
- Agent ID header not provided
Authorization Errors (403)
INSUFFICIENT_PERMISSIONS
- Agent lacks required permissions
Rate Limiting (429)
RATE_LIMIT
- Rate limit exceeded
Configuration Errors (500)
CONFIG_ERROR
- Invalid configurationSUPABASE_ERROR
- Supabase connection or query error
Database Schema
agent_cards
Column | Type | Description |
---|---|---|
id | UUID | Primary key |
agent_id | TEXT | Unique agent identifier |
name | TEXT | Human-readable name |
description | TEXT | Optional description |
permissions | TEXT[] | Array of permissions |
public_key | TEXT | RSA public key (PEM format) |
endpoints | JSONB | API endpoints |
metadata | JSONB | Custom metadata |
created_at | TIMESTAMPTZ | Creation timestamp |
updated_at | TIMESTAMPTZ | Last update timestamp |
phlow_audit_logs
Column | Type | Description |
---|---|---|
id | UUID | Primary key |
timestamp | TIMESTAMPTZ | Event timestamp |
event | TEXT | Event type |
agent_id | TEXT | Agent that triggered event |
target_agent_id | TEXT | Target agent (optional) |
details | JSONB | Additional event details |
created_at | TIMESTAMPTZ | Record creation timestamp |
RLS Policies
Basic Agent Access
CREATE POLICY agent_access ON table_name
FOR ALL
USING (
auth.jwt() ->> 'sub' IS NOT NULL
AND EXISTS (
SELECT 1 FROM agent_cards
WHERE agent_id = auth.jwt() ->> 'sub'
)
);
Agent-Specific Access
CREATE POLICY agent_own_data ON table_name
FOR ALL
USING (agent_id = auth.jwt() ->> 'sub');
Permission-Based Access
CREATE POLICY admin_only ON table_name
FOR ALL
USING (auth.jwt() -> 'permissions' ? 'admin:users');