Skip to content

feat: add JWT auth middleware to Autonomic HTTP API#2

Merged
broomva merged 1 commit intomainfrom
feat/autonomic-jwt-auth
Mar 20, 2026
Merged

feat: add JWT auth middleware to Autonomic HTTP API#2
broomva merged 1 commit intomainfrom
feat/autonomic-jwt-auth

Conversation

@broomva
Copy link
Copy Markdown
Owner

@broomva broomva commented Mar 20, 2026

Summary

  • Protect sensitive endpoints (/gating/{session_id}, /projection/{session_id}) with JWT authentication using lago-auth validation primitives
  • Keep /health unprotected for Railway/load balancer health checks
  • Backward-compatible: no AUTONOMIC_JWT_SECRET or AUTH_SECRET env var = no auth (local dev mode), with a logged warning

Changes

  • Add lago-auth and jsonwebtoken as workspace dependencies
  • New auth.rs module in autonomic-api with AuthConfig (from-env, with-secret, disabled) and auth_middleware
  • Split axum router into public routes (health) and protected routes (gating, projection) with auth applied as a route_layer
  • Update autonomicd daemon to load AuthConfig::from_env() at startup
  • 9 new auth tests + 2 existing tests updated = 11 total in autonomic-api (95 workspace-wide)

Auth flow

  1. On startup, daemon reads AUTONOMIC_JWT_SECRET (or falls back to AUTH_SECRET)
  2. If no secret found: all endpoints are open (local dev)
  3. If secret found: /gating and /projection require Authorization: Bearer <jwt> header
  4. JWT validated using lago-auth::jwt::validate_jwt (HS256, checks expiry + subject)

Test plan

  • /health without token returns 200 (auth enabled)
  • /gating/{id} without token returns 401 (auth enabled)
  • /gating/{id} with invalid token returns 401
  • /gating/{id} with wrong-secret token returns 401
  • /gating/{id} with valid token returns 200
  • /projection/{id} without token returns 401 (auth enabled)
  • /projection/{id} with valid token returns 200
  • All endpoints work without token when auth disabled (local dev)
  • cargo clippy --workspace -- -D warnings clean
  • cargo test --workspace — 95/95 passing

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Implemented JWT authentication for protecting sensitive API endpoints
    • Gating and projection endpoints now require valid authentication tokens for access
    • Health endpoint remains publicly accessible
    • Authentication support is configurable and can be disabled when needed
    • Unauthorized requests receive 401 Unauthorized responses

Protect /gating/{session_id} and /projection/{session_id} endpoints with
JWT authentication while keeping /health unprotected for Railway health
checks. Uses lago-auth JWT validation primitives (validate_jwt,
extract_bearer_token) with a simpler middleware that skips session mapping.

Auth is backward-compatible: if no AUTONOMIC_JWT_SECRET or AUTH_SECRET
env var is configured, the API starts without auth (local dev mode) but
logs a warning. When a secret IS set, valid Bearer tokens are required.

- Add lago-auth and jsonwebtoken as workspace dependencies
- New auth.rs module in autonomic-api with AuthConfig and auth_middleware
- Split router into public (health) and protected (gating, projection) route groups
- 9 new tests covering auth enabled/disabled, valid/invalid/missing tokens
- All 95 workspace tests passing, clippy clean

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 20, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 61ce5b79-0574-4bb2-92bc-a37917ef19dc

📥 Commits

Reviewing files that changed from the base of the PR and between 71b2d75 and 1ad1261.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • Cargo.toml
  • crates/autonomic-api/Cargo.toml
  • crates/autonomic-api/src/auth.rs
  • crates/autonomic-api/src/lib.rs
  • crates/autonomic-api/src/router.rs
  • crates/autonomicd/src/main.rs

📝 Walkthrough

Walkthrough

A new JWT authentication system is integrated into the autonomic API. The changes add lago-auth and jsonwebtoken dependencies, introduce an AuthConfig struct that reads secrets from environment variables, implement Axum middleware for token validation, and protect /gating and /projection endpoints while leaving /health public. Authentication can be disabled via configuration.

Changes

Cohort / File(s) Summary
Dependencies
Cargo.toml, crates/autonomic-api/Cargo.toml
Added lago-auth (0.2.1, workspace) and jsonwebtoken (9) dependencies to support JWT authentication.
Auth Module
crates/autonomic-api/src/auth.rs
New module implementing AuthConfig struct with environment-based secret loading, disabled mode, and Axum middleware auth_middleware that validates bearer tokens or returns 401 Unauthorized JSON responses.
Public API
crates/autonomic-api/src/lib.rs
Exports new auth module and AuthConfig type; adds build_router_with_auth export alongside existing build_router.
Router Integration
crates/autonomic-api/src/router.rs
Refactors build_router to delegate to build_router_with_auth; mounts /health as unprotected, wraps /gating and /projection with auth middleware; expands tests to verify 401 responses for missing/invalid tokens and 200 for valid tokens.
Application Setup
crates/autonomicd/src/main.rs
Updates to create AuthConfig::from_env() and call build_router_with_auth instead of build_router.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Router
    participant AuthMiddleware
    participant JWTLib as JWT Lib<br/>(lago-auth)
    participant Handler

    Client->>Router: GET /gating/{session_id}
    Router->>AuthMiddleware: Route through middleware
    AuthMiddleware->>AuthMiddleware: Check if auth enabled
    
    alt Auth Enabled
        AuthMiddleware->>AuthMiddleware: Extract Bearer token<br/>from Authorization header
        alt Token Missing
            AuthMiddleware-->>Client: 401 Unauthorized JSON
        else Token Present
            AuthMiddleware->>JWTLib: validate_jwt(token, secret)
            alt Valid Token
                JWTLib-->>AuthMiddleware: ✓ Valid
                AuthMiddleware->>Handler: Pass request through
                Handler-->>Client: 200 OK
            else Invalid/Expired
                JWTLib-->>AuthMiddleware: ✗ Error
                AuthMiddleware-->>Client: 401 Unauthorized JSON
            end
        end
    else Auth Disabled
        AuthMiddleware->>Handler: Pass request through
        Handler-->>Client: 200 OK
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Hop along with tokens secure,
A JWT guard stands at the door,
/gating and /projection now assured,
While /health hops freely as before,
Auth awakens, the API's allure! 🔐

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/autonomic-jwt-auth

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@broomva broomva merged commit 3eb8c3b into main Mar 20, 2026
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant