Skip to main content

HMAC Auth Filter

Before You Change Anything

Security pages describe boundaries that protect shared systems and user data. Validate the boundary you are changing before you test or modify anything.

The HMAC auth filter is a WebAssembly (WASM) module running at the Envoy Gateway edge.

In plain language, this filter is the bouncer for the mobile-only auth path. It checks that a request carries the expected signed device headers before the backend sees it.

This page explains what it does, how the signature scheme works, and how it fits alongside Envoy's JWT SecurityPolicy.

What The Filter Does

For every incoming request that uses X-Token authentication, the filter runs four validation steps.

Read these steps as "do the required pieces exist, are they well formed, are they fresh, and does the signature match?"

1
Step 1

Check required headers

The filter first verifies that X-Timestamp, X-Signature, X-Device-Info, and X-Version are present.

If any are missing, the request is rejected with 401 Unauthorized.

2
Step 2

Parse the timestamp

The filter parses X-Timestamp as an RFC3339Nano timestamp.

If parsing fails, the request is rejected with 400 Bad Request.

3
Step 3

Validate freshness

The timestamp must be within a 2-minute window, with an extra 30-second tolerance for clock skew.

If the timestamp is too old or too far in the future, the request is rejected with 403 Forbidden.

4
Step 4

Validate the signature

The filter computes the expected HMAC-SHA256 signature and compares it to X-Signature using constant-time comparison.

expected = HMAC-SHA256(secret, token + ":" + timestamp)

Here, secret is the shared key in the WASM filter, token is X-Token, and timestamp is X-Timestamp. A mismatch returns 403 Forbidden.

The HMAC Scheme

The signature formula is:

signature = HMAC-SHA256(secret, token + ":" + timestamp)

Including the timestamp in the signed payload is what makes freshness validation meaningful. An attacker cannot change the timestamp to extend the replay window without invalidating the signature.

How It Fits With JWT Validation

The WASM filter is only one layer of the mobile auth path. The full request path is:

LayerWhat It Catches
Edge (WASM filter)Validates device-bound HMAC headers when X-Token is present
Edge (SecurityPolicy)Validates the Firebase JWT from X-Token or Authorization
Backend (middleware)Reads trusted X-Firebase-* headers and applies local/test or e2e bypass rules

There is no second mobile-HMAC validation inside the orchestrator.

That is intentional. The edge is responsible for rejecting bad mobile signatures before the request reaches backend code.

Environment Skip

In local and test environments, the filter passes all requests through without validation. This mirrors the backend middleware behavior, which injects a default principal in those environments.

The filter also skips WebSocket upgrade requests. Socket.IO connections use the JWT path at the edge and socket-level auth inside the realtime server.

Build Pipeline

The filter is built from Go source (crawbl-backend/cmd/envoy-auth-filter/main.go), compiled to WASM via TinyGo, packaged as a Docker image, and deployed through an EnvoyExtensionPolicy:

Go source -> TinyGo (target: wasi) -> filter.wasm -> Docker image -> EnvoyExtensionPolicy

The policy targets the public gateway and uses failOpen: false, so requests are rejected if the filter cannot be loaded.

Secret Locations

Mobile Edge HMAC

The mobile HMAC secret lives in AWS Secrets Manager at crawbl/dev/edge/hmac and is synced into the hmac-wasm-config Kubernetes Secret used by the WASM plugin.

Internal MCP HMAC

Crawbl also uses a separate HMAC scheme for internal MCP communication between ZeroClaw runtimes and the orchestrator's MCP server.

Each ZeroClaw pod receives a signed bearer token at provisioning time. The token encodes the user's internal database UUID and workspace ID:

base64url(userID:workspaceID).hmac_hex

The shared signing key (CRAWBL_MCP_SIGNING_KEY) is stored in AWS Secrets Manager and synced into the orchestrator-vault-secrets Kubernetes Secret used by the orchestrator and userswarm-webhook deployment.

What's Next

Head to the Developer Guides for practical guides on testing, deploying, and debugging the platform.