Authentication
Understanding authentication in the Runbeam ecosystem.
Overview
The Runbeam platform uses a multi-layered authentication approach that balances security, usability, and autonomous operation. This guide explains how authentication works across Runbeam Cloud, Harmony Proxy, the CLI, and the SDK.
Authentication Layers
User Authentication (OAuth/OIDC)
Purpose: Human users accessing Runbeam Cloud
How it works:
- User logs in via OAuth/OIDC provider
- Runbeam issues a JWT token (RS256 signed)
- Token contains user identity and permissions
- Token is valid for a limited time (typically 24 hours)
Used by:
- Web UI access to Runbeam Cloud
- CLI login (
runbeam login) - SDK applications during initial setup
API Tokens (Laravel Sanctum)
Purpose: Programmatic access to Runbeam Cloud API
How it works:
- User creates API token in Runbeam Cloud
- Token format:
{id}|{plaintext_token} - Server validates token on each request
- Tokens can have granular permissions
Used by:
- SDK applications (alternative to JWT)
- Custom integrations
- CI/CD pipelines
Machine Tokens
Purpose: Autonomous operation of Harmony gateways
How it works:
- User (via CLI or SDK) requests gateway authorization
- Runbeam Cloud issues machine-scoped token
- Token is valid for 30 days
- Token is stored encrypted on the gateway
- Gateway uses token for autonomous API access
Used by:
- Harmony Proxy connecting to Runbeam Cloud
- Automatic configuration updates
- Gateway health reporting
JWT Token Validation
JWT tokens in Runbeam use RS256 (asymmetric cryptography) for security:
Structure
eyJhbGci... (Header - algorithm, key ID)
eyJzdWI... (Payload - user info, expiry)
SflKxwR... (Signature - cryptographic proof)
Validation Process
- Extract Key ID from JWT header
- Fetch Public Key from JWKS endpoint (cached 1 hour)
- Verify Signature using RS256 algorithm
- Check Expiry (exp), Not Before (nbf), Issued At (iat)
- Validate Issuer and Audience claims
Why RS256?
- Asymmetric: Private key stays on server, public keys distributed
- Key Rotation: Multiple keys can be active (via
kid) - Offline Validation: Clients verify locally without server calls
- Standards Compliant: Industry standard for OAuth/OIDC
Authorization Flow
Gateway Authorization
The most common authorization flow - connecting Harmony to Runbeam Cloud:
┌─────────┐ ┌─────────┐ ┌──────────────┐ ┌─────────┐
│ CLI │─────▶│ Harmony │─────▶│ Runbeam Cloud│─────▶│ Gateway │
│ │ (1) │ Proxy │ (2) │ │ (3) │ Token │
└─────────┘ └─────────┘ └──────────────┘ └─────────┘
│ │ │
│ │ │
└─────────────────────────────────────┴────────────────────┘
(4) Encrypted storage
Step-by-step:
- User Login: User runs
runbeam login, authenticates via browser - CLI to Harmony: User runs
runbeam harmony:authorize, CLI sends user token to Harmony - Harmony to Cloud: Harmony validates user JWT, requests machine token from Runbeam Cloud
- Token Exchange: Runbeam Cloud issues 30-day machine token
- Secure Storage: Harmony encrypts and stores machine token
- Autonomous Operation: Harmony uses machine token for ongoing API access
Pre-Provisioned Tokens
For headless deployments where interactive authorization isn't possible:
# Export machine token (obtained from Runbeam Cloud)
export RUNBEAM_MACHINE_TOKEN='{
"machine_token":"mt_abc...",
"expires_at":"2025-12-31T23:59:59Z",
"gateway_id":"gw-123",
"gateway_code":"prod-gw",
"abilities":[],
"issued_at":"2025-01-01T00:00:00Z"
}'
# Optionally set encryption key for persistence
export RUNBEAM_ENCRYPTION_KEY=AGE-SECRET-KEY-...
# Start Harmony - token is used automatically
./harmony-proxy --config config.toml
Token Storage
Security Requirements
Tokens must never be stored in plaintext on disk. The Runbeam ecosystem uses:
-
OS Keyring (preferred)
- macOS: Keychain
- Linux: Secret Service API (freedesktop.org)
- Windows: Credential Manager
-
Encrypted Filesystem (fallback)
- age X25519 encryption
- Restrictive file permissions (0600 on Unix)
- Instance-specific encryption keys
Encryption Key Management
For encrypted filesystem storage, keys are sourced from:
Priority order:
- CLI-provided key (via
/admin/authorizerequest) RUNBEAM_ENCRYPTION_KEYenvironment variable- Auto-generated key at
~/.runbeam/<instance_id>/encryption.key
Production recommendation: Use environment variable for consistency:
# Generate key (Linux/macOS)
export RUNBEAM_ENCRYPTION_KEY=$(age-keygen | grep AGE-SECRET-KEY | base64 -w 0)
# Store in secret manager (example with AWS Secrets Manager)
aws secretsmanager create-secret \
--name harmony-encryption-key \
--secret-string "$RUNBEAM_ENCRYPTION_KEY"
Security Best Practices
For Development
- Use
runbeam loginfor interactive authentication - Let OS keyring handle token storage
- Rotate tokens regularly
For Production
- Use
RUNBEAM_ENCRYPTION_KEYenvironment variable - Store encryption keys in secret manager (Vault, AWS, Azure)
- Enable
RUNBEAM_MACHINE_TOKENfor headless deployments - Monitor token expiry and renew before 30 days
- Use separate gateways for different environments
Token Rotation
Machine tokens expire after 30 days. To rotate:
# Re-authorize before expiry
runbeam harmony:authorize -l my-gateway
# Or programmatically via SDK
let response = client.authorize_gateway(
user_token,
gateway_id,
None,
None
).await?;
Troubleshooting
JWT Validation Fails
Symptoms: "Invalid signature" or "Token expired"
Solutions:
- Check system clock is synchronized
- Verify JWKS endpoint is accessible
- Ensure token hasn't expired
- Check
RUNBEAM_JWKS_TTLif using custom cache duration
Machine Token Expired
Symptoms: Harmony can't connect to Runbeam Cloud
Solutions:
- Check token expiry:
runbeam harmony:info -l my-gateway - Re-authorize:
runbeam harmony:authorize -l my-gateway - For automated renewal, set up cron job or monitoring alert at 25 days
Storage Backend Issues
Symptoms: "Failed to save token" or "Keyring unavailable"
Solutions:
- Check OS keyring service is running (Linux:
secret-tool) - Verify file permissions on
~/.runbeam/ - Set
RUNBEAM_ENCRYPTION_KEYexplicitly for encrypted filesystem fallback - Check logs:
RUST_LOG=debug runbeam ...
Next Steps
- Runbeam CLI → - Using the CLI
- Runbeam SDK → - Integrating with the SDK