Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Calimero Authentication Service
A production-ready forward authentication service implementing hierarchical key management with pluggable providers and comprehensive security features.
Architecture Overview
The service implements Forward Authentication pattern where a reverse proxy delegates authentication decisions to this service. The node remains completely authentication-unaware.
┌─────────────┐ ┌──────────────┐ ┌─────────────┐ ┌──────────┐
│ Client │───▶│ Reverse Proxy│───▶│ Auth Service│ │ Node │
│ │ │ (nginx/ │ │ │ │ │
│ │ │ traefik) │ │ │ │ │
└─────────────┘ └──────────────┘ └─────────────┘ └──────────┘
│ │
│ │
▼ ▼
/auth/validate JWT validation
(token check) & permission check
Key Components
- Hierarchical Keys: Root keys (identity) + Client keys (context-scoped)
- Provider System: Pluggable authentication backends
- Secret Management: Encrypted storage of JWT secrets and keys
- Permission System: Granular resource-based permissions
- Storage Layer: Pluggable storage backends (RocksDB, Memory)
Quick Start
Development Mode
# Run with minimal configuration
# Test endpoints
Production Mode
# With configuration file
Configuration
Basic Configuration (config.toml)
= "0.0.0.0:3001"
[]
= "calimero-auth"
= 3600 # 1 hour
= 2592000 # 30 days
[]
= "rocksdb" # or "memory"
= "/data/auth_db"
[]
= true
= ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
= ["Authorization", "Content-Type", "Accept"]
[]
= 1048576 # 1MB
[]
= 50
= 5
[]
= true
= 31536000
= "DENY"
[]
= true
[]
= "testnet"
= "https://rpc.testnet.near.org"
= "https://wallet.testnet.near.org"
Environment Variables
All configuration can be overridden via environment variables using AUTH_ prefix:
AUTH_LISTEN_ADDR="0.0.0.0:3001"
AUTH_JWT__ISSUER="my-issuer"
AUTH_STORAGE__TYPE="rocksdb"
AUTH_STORAGE__PATH="/data/auth"
AUTH_PROVIDERS__NEAR_WALLET=true
Root and Client Keys
Hierarchical Key System
The service implements a two-tier key system:
-
Root Keys - Identity-level authentication
- Prove "who you are"
- Created through provider authentication (wallet, OAuth, etc.)
- Can create client keys with limited permissions
- Long-lived, user-managed
-
Client Keys - Context-scoped authorization
- Grant "what you can do" in specific contexts
- Inherit subset of root key permissions
- Short-lived, application-managed
- Tied to specific contexts/resources
Key Lifecycle
graph TD
A[User Authentication] --> B[Root Key Created]
B --> C[Root Key Permissions Set]
C --> D[Client Key Request]
D --> E[Permission Validation]
E --> F[Client Key Generated]
F --> G[Context-Scoped Access]
Key Storage Structure
Keys:
├── root:{key_id} # Root key data
├── client:{key_id} # Client key data
├── root_clients:{root_id} # Client key index
└── permissions:{key_id} # Key permissions
Authentication Flow
1. Root Key Authentication
# Get challenge
# Sign challenge with wallet (browser/CLI)
# Exchange for root key JWT
2. Client Key Generation
# Use root key to generate client key
API Endpoints
Public Endpoints (No Authentication)
GET /auth/login # React SPA for authentication
GET /auth/challenge # Get signing challenge
POST /auth/token # Exchange challenge for root key JWT
POST /auth/refresh # Refresh expired tokens
GET /auth/providers # List available providers
GET /auth/identity # Service information
GET /auth/validate # Forward auth validation endpoint
POST /auth/validate # (same as above, for proxies)
Protected Endpoints (Require Root Key JWT)
# Root Key Management
GET /admin/keys # List root keys
POST /admin/keys # Create root key
DELETE /admin/keys/{key_id} # Delete root key
# Client Key Management
GET /admin/keys/clients # List client keys
POST /admin/client-key # Generate client key
DELETE /admin/keys/{key_id}/clients/{client_id} # Delete client key
# Permission Management
GET /admin/keys/{key_id}/permissions # Get key permissions
PUT /admin/keys/{key_id}/permissions # Update permissions
# Token Management
POST /admin/revoke # Revoke current token
# System
GET /admin/metrics # Service metrics
Permissions System
Permission Structure
Permission Examples
Permission Validation
The service validates permissions for each request by:
- Extracting JWT from Authorization header
- Decoding token and extracting permissions
- Matching request path/method to required permissions
- Allowing/denying based on permission check
Path-to-Permission Mapping
// Example mappings in validator.rs
"/admin/keys" + GET "/admin/keys" + POST "/admin/contexts/{id}"
Authentication Providers
Provider Interface
Available Providers
NEAR Wallet Provider (near_wallet)
- Location:
src/providers/impls/near_wallet.rs - Authentication: NEAR wallet signature verification
- Configuration: Network, RPC URL, wallet URL
- Flow: Challenge → Sign → Verify → Root Key
Creating Custom Providers
// src/providers/impls/my_provider.rs
Provider Registration
// src/providers/mod.rs
Storage Layer
Storage Interface
Available Storage Backends
RocksDB Storage (Production)
[]
= "rocksdb"
= "/data/auth_db"
Memory Storage (Development)
[]
= "memory"
Custom Storage Implementation
Secret Management
JWT Secret Handling
The service automatically generates and manages JWT signing secrets:
- Secret Generation: 32-byte cryptographically secure random secrets generated on first startup
- Storage: Stored as base64-encoded JSON in the configured storage backend
- Key Rotation: Supports secret rotation with grace periods (24h rotation, 48h grace period)
- Security: Secrets never logged or exposed, stored with versioning and expiration
Secret Storage Structure
Secrets:
├── system:secrets:jwt_auth # JWT auth signing secret
├── system:secrets:jwt_challenge # JWT challenge signing secret
├── system:secrets:csrf # CSRF protection secret
├── system:secrets:jwt_auth_backup # Backup auth secret
├── system:secrets:jwt_challenge_backup # Backup challenge secret
└── system:secrets:csrf_backup # Backup CSRF secret
Secret Manager Interface
Security Details
- Secret Generation: Cryptographically secure random number generation
- Storage Format: JSON serialized with base64-encoded secret values
- Rotation: Automatic rotation with configurable intervals and grace periods
- Backup Strategy: Primary + backup storage locations for resilience
- Memory Safety: Secrets cleared from memory after use
Request Handlers
Handler Structure
All handlers follow this pattern:
pub async
Response Format
Error Response
Key Handlers
Authentication Handlers (src/api/handlers/auth.rs)
login_handler: Serves React SPA for interactive authchallenge_handler: Generates signing challengestoken_handler: Exchanges signed challenge for JWTrefresh_token_handler: Refreshes expired tokensvalidate_handler: Validates tokens for forward auth
Key Management Handlers (src/api/handlers/root_keys.rs, src/api/handlers/client_keys.rs)
list_keys_handler: Lists user's keyscreate_key_handler: Creates new root keysdelete_key_handler: Revokes keysgenerate_client_key_handler: Creates client keys
Permission Handlers (src/api/handlers/permissions.rs)
get_key_permissions_handler: Gets key permissionsupdate_key_permissions_handler: Updates permissions
Development
Running Tests
# Unit tests
# Integration tests
# Specific test module
Development Mode
# Enable debug logging
RUST_LOG=debug
# Test with curl
Frontend Development
Production Deployment
Docker
FROM rust:1.75 as builder
WORKDIR /app
COPY . .
RUN cargo build --release --bin calimero-auth
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates
COPY --from=builder /app/target/release/calimero-auth /usr/local/bin/
EXPOSE 3001
CMD ["calimero-auth", "--config", "/config/auth.toml"]
Reverse Proxy Configuration
Nginx
server {
listen 80;
server_name api.example.com;
# Auth service routes
location /auth/ {
proxy_pass http://auth:3001;
}
location /admin/ {
proxy_pass http://auth:3001;
}
# Protected routes (forward auth)
location / {
auth_request /auth-check;
proxy_pass http://node:2428;
}
location = /auth-check {
internal;
proxy_pass http://auth:3001/auth/validate;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
}
Traefik
# docker-compose.yml
services:
auth:
image: calimero/auth:latest
labels:
- "traefik.http.routers.auth.rule=PathPrefix(`/auth`) || PathPrefix(`/admin`)"
- "traefik.http.middlewares.auth-forward.forwardauth.address=http://auth:3001/auth/validate"
node:
image: calimero/node:latest
labels:
- "traefik.http.routers.node.rule=!PathPrefix(`/auth`) && !PathPrefix(`/admin`)"
- "traefik.http.routers.node.middlewares=auth-forward"
Security Features
Built-in Security
- Rate Limiting: Configurable request limiting
- CORS: Cross-origin request handling
- Security Headers: HSTS, CSP, X-Frame-Options
- Input Validation: Request validation with error handling
- JWT Security: Short-lived tokens with refresh rotation
Security Headers
// Automatically added security headers
"Strict-Transport-Security": "max-age=31536000; includeSubDomains"
"X-Frame-Options": "DENY"
"X-Content-Type-Options": "nosniff"
"Referrer-Policy": "strict-origin-when-cross-origin"
"Content-Security-Policy": "default-src 'self'; script-src 'self' 'unsafe-inline'"
Monitoring
Health Checks
# Service health
# Service identity
Metrics (Protected)
Logging
# Configure logging levels
RUST_LOG=calimero_auth=debug,tower_http=info
Troubleshooting
Common Issues
-
"No authentication providers available"
- Check provider configuration in config.toml
- Ensure provider dependencies are available
-
"Storage initialization failed"
- Check storage path permissions
- Verify storage type configuration
-
"JWT secret generation failed"
- Check storage write permissions
- Verify storage backend is accessible
-
"Forward auth validation failed"
- Check reverse proxy configuration
- Verify auth endpoint is reachable
- Check JWT token format
Debug Mode
RUST_LOG=trace
License
Licensed under MIT OR Apache-2.0