18. Security Model
OpenCLaw operates with significant access to user data and system resources. The security model must prevent unauthorized access, limit damage from compromised components, and provide audit capability.
Authentication Framework
Access to OpenCLaw requires authentication. Local deployments support password authentication, OAuth providers, and local certificate-based authentication for trusted networks.
# security.py
from dataclasses import dataclass
from typing import Optional, List
from datetime import datetime, timedelta
import hashlib
import secrets
@dataclass
class AuthToken:
token_hash: str
user_id: str
scope: List[str]
created: datetime
expires: datetime
def is_valid(self) -> bool:
return datetime.utcnow() < self.expires
class AuthenticationService:
def __init__(self, token_ttl: timedelta = timedelta(hours=24)):
self.token_ttl = token_ttl
self.tokens = {}
self.password_hashes = {}
def authenticate(
self,
username: str,
password: str
) -> Optional[AuthToken]:
stored_hash = self.password_hashes.get(username)
if not stored_hash:
return None
if not self.verify_password(password, stored_hash):
return None
return self.create_token(username, scope=['full'])
def create_token(self, user_id: str, scope: List[str]) -> AuthToken:
raw_token = secrets.token_urlsafe(32)
token_hash = hashlib.sha256(raw_token.encode()).hexdigest()
token = AuthToken(
token_hash=token_hash,
user_id=user_id,
scope=scope,
created=datetime.utcnow(),
expires=datetime.utcnow() + self.token_ttl
)
self.tokens[token_hash] = token
return token
def verify_token(self, token_str: str) -> Optional[AuthToken]:
token_hash = hashlib.sha256(token_str.encode()).hexdigest()
token = self.tokens.get(token_hash)
if not token or not token.is_valid():
return None
return token
def verify_password(self, password: str, stored_hash: str) -> bool:
return self._hash(password) == stored_hash
def _hash(self, password: str) -> str:
salt = stored_hash[:32] # First 32 chars are salt
return hashlib.pbkdf2_hmac(
'sha256',
password.encode(),
salt.encode(),
100000
)
Authorization Layer
Beyond authentication, authorization controls what authenticated users can do. OpenCLaw implements capability-based authorization where operations require specific capabilities.
class AuthorizationService:
CAPABILITY_MAPPING = {
'system:read': ['status', 'conversations:read'],
'system:write': ['settings:modify', 'plugins:install'],
'system:admin': ['all'],
}
def __init__(self, auth_service: AuthenticationService):
self.auth = auth_service
self.user_capabilities = {}
def check_permission(
self,
token: AuthToken,
required_capability: str
) -> bool:
if 'all' in token.scope:
return True
return required_capability in token.scope
def grant_capabilities(self, user_id: str, capabilities: List[str]):
self.user_capabilities[user_id] = capabilities
Audit Logging
Security-relevant events log to an immutable audit trail. Logs capture authentication attempts, authorization decisions, configuration changes, and data access patterns.
class AuditLogger:
def __init__(self, storage_path: str):
self.storage = append_only_storage(storage_path)
def log(
self,
event_type: str,
user_id: str,
resource: str,
outcome: str,
metadata: dict = None
):
entry = {
'timestamp': datetime.utcnow().isoformat(),
'event_type': event_type,
'user_id': user_id,
'resource': resource,
'outcome': outcome,
'metadata': metadata or {}
}
self.storage.append(json.dumps(entry))
Implement a rate limiting mechanism for authentication attempts. Design the lockout policy and account recovery flow that balances security with usability.