Auth Service
mero-auth
Purpose
Forward authentication service for the Calimero node. Handles JWT issuing and verification, pluggable authentication providers (NEAR, Ethereum, custom), a challenge/nonce flow for wallet-based auth, and key management. Can run embedded in the Axum server or behind an external reverse proxy.
Architecture
The AuthService coordinates four subsystems: token management, provider routing, key storage, and secret management. Incoming token requests are routed by auth_method to the appropriate provider.
JWT Details
Token structure, claims schema, and the challenge-based authentication flow.
TokenManager
Encodes and decodes JWTs using the jsonwebtoken crate. Configured via JwtConfig which specifies algorithm (HS256/HS384), secret rotation policy, and expiration windows for access and refresh tokens.
TokenType
Two token variants with different lifetimes and permissions scope.
Access, // short-lived, carries permissions
Refresh, // long-lived, exchange for new access
}
Claims Schema
sub: String, // key id (public key hash)
iss: String, // issuer (node identity)
aud: String, // audience
exp: u64, // expiration timestamp
iat: u64, // issued at
jti: String, // unique token id (UUID)
permissions: Vec<String>, // granted permissions
node_url: Option<String>, // optional node URL
}
ChallengeClaims
challenge: String, // random nonce string
exp: u64, // challenge expiration (short TTL)
iat: u64, // issued at
}
Challenge / Nonce Authentication Flow
Request Challenge
Client calls the challenge endpoint. The AuthService generates a random nonce, wraps it in ChallengeClaims, and returns a short-lived challenge JWT (e.g. 5-minute TTL).
Sign Challenge
Client signs the challenge nonce with their wallet key (NEAR Ed25519, Ethereum secp256k1, etc.). The signature proves ownership of the corresponding public key without revealing the private key.
Submit Signed Challenge
Client sends the signed challenge back along with their public key and auth_method. The appropriate AuthProvider verifies the signature against the public key and challenge nonce.
Issue Tokens
On successful verification, TokenManager generates an access token and refresh token with the authenticated key ID as sub claim. Tokens are returned to the client for subsequent API calls.
Auth Modes
Two operational modes that determine how authentication is enforced on incoming requests.
Proxy Mode
externalNo in-process JWT verification. Authentication is handled by an external reverse proxy (nginx, Envoy, etc.) that sits in front of the Calimero node. The proxy validates tokens and forwards authenticated requests with identity headers.
The node trusts the proxy's identity injection and does not perform any token validation itself. Suitable for enterprise deployments with existing auth infrastructure.
struct ProxyConfig {
trusted_header: String, // e.g. "X-Auth-Key"
}
Embedded Mode
recommendedFull JWT lifecycle managed in-process. The AuthGuardLayer middleware intercepts every request, extracts the token from the Authorization: Bearer header or ?token= query parameter, and verifies it against the local secret.
On successful verification, an AuthenticatedKey is injected into the Axum request extensions, making the caller's identity available to all downstream handlers.
struct AuthGuardLayer {
token_manager: Arc<TokenManager>,
}
// Injected into request extensions
struct AuthenticatedKey {
key_id: String,
permissions: Vec<String>,
}
Storage
Auth state can be persisted in RocksDB (production) or held in-memory (development/testing). The storage backend is selected at initialization and abstracted behind a trait interface.
RocksDB Backend
Persistent storage for signing keys, refresh token metadata, and revocation lists. Uses a dedicated column family within the node's RocksDB instance. Survives node restarts.
In-Memory Backend
Ephemeral storage for development and testing. All auth state is lost on restart. Useful for local development where persistent tokens are unnecessary.
API Reference
Public Endpoints
Protected Endpoints
Deployment
Nginx (Forward Auth)
Configure auth_request to proxy to /auth/validate. Protected routes get validated transparently. Auth routes (/auth/*, /admin/*) proxy directly to the auth service.
Traefik
Use forwardauth.address middleware pointing to http://auth:3001/auth/validate. Label auth service routes with PathPrefix(/auth) and node routes with the forward-auth middleware.
Configuration
All settings can be overridden via AUTH_-prefixed environment variables (e.g. AUTH_JWT__ISSUER, AUTH_STORAGE__TYPE).