Skip to content

SOL_EDDSA JWT tokens rejected by BitRouter v0.6.1 after plugin reinstall (signature verification mismatch) #15

@openclaw-bitrouterai

Description

@openclaw-bitrouterai

Problem

After applying the SOL_EDDSA fix from c584351 and reinstalling the plugin, BitRouter v0.6.1 still rejects all JWT tokens with 401: unauthorized: invalid JWT signature. The migration path from issue #12 does not result in working authentication.

This is distinct from #12 (format incompatibility) and #13 (stale credential in openclaw store). Both of those are necessary preconditions, but even after:

  1. Plugin reinstalled with the c584351 fix
  2. New web3/SOL_EDDSA keypair generated (master.json with "algorithm": "web3")
  3. New SOL_EDDSA JWT minted and written to all agent auth-profiles.json files
  4. bitrouter.db re-created with the new account

...BitRouter's Rust-based JWT verifier still returns invalid JWT signature on every /v1/chat/completions request.

Reproduction

Environment: OpenClaw v2026.3.8, BitRouter binary v0.6.1, macOS (darwin arm64)

# 1. Start with a working v0.4.x EdDSA setup
# 2. Install the updated plugin
openclaw plugins install ~/projects/bitrouter-plugins/openclaw

# 3. Verify new key was generated
cat ~/.openclaw/bitrouter/.keys/$(cat ~/.openclaw/bitrouter/.keys/active)/master.json
# Shows: { "algorithm": "web3", "seed": "..." }

# 4. Verify JWT was updated in agent auth profiles  
cat ~/.openclaw/agents/marketing/agent/auth-profiles.json
# Shows new SOL_EDDSA JWT with header {"alg":"SOL_EDDSA","typ":"JWT"}

# 5. Any LLM call through BitRouter fails
# POST http://127.0.0.1:8787/v1/chat/completions -> 401

Evidence from logs

Cron run logs show the progression:

  • Mar 11: Last successful run (old EdDSA key)
  • Mar 12 (after first reinstall): "error": "HTTP 401: unauthorized: malformed JWT" — BitRouter couldn't parse the token format
  • Mar 12 (after second reinstall with new SOL_EDDSA key): "error": "HTTP 401: unauthorized: invalid JWT signature" — format recognized, but signature fails
  • Mar 13–15: Continuous invalid JWT signature on every cron run and heartbeat

BitRouter runtime logs:

[bitrouter] POST /v1/chat/completions ... unable to serve request (client error) status=401
[agent/embedded] embedded run agent end: isError=true error=HTTP 401: unauthorized: invalid JWT signature

Suspected root cause

The plugin's TypeScript JWT signing (auth.ts) derives the Ed25519 keypair from the 32-byte seed differently than BitRouter's Rust verifier does under the SOL_EDDSA algorithm. Specifically:

  • The plugin uses the seed from master.json to derive a keypair and sign the JWT
  • BitRouter v0.6.1's Rust code uses the iss claim (a Solana base58 public key) to verify the signature
  • If the public key derived in TypeScript doesn't match what BitRouter derives from the same seed, or if the signing uses a different Ed25519 curve point derivation (e.g., NaCl sign.keyPair.fromSeed vs Solana Keypair.fromSeed), the signature will never verify

This would explain why the format is recognized (SOL_EDDSA header accepted) but the signature itself fails.

Impact

All agent functionality that routes through BitRouter is broken:

  • All cron jobs for the marketing agent (feed scan, content drafts, weekly planning)
  • Marketing agent heartbeats (every 30 min, all returning 401)
  • Any agent tool that calls BitRouter (bitrouter_status, bitrouter_list_routes, etc.)
  • The main agent is unaffected only because it falls through to direct OpenRouter calls

This has been broken for 4+ days with no automatic recovery path.

Current workaround

Revert to the old EdDSA key:

# Point active back to the old key
echo "f9RxXGCNZq1h_R8P" > ~/.openclaw/bitrouter/.keys/active
# Delete bitrouter.db so it re-registers with the old key
rm ~/.openclaw/bitrouter/bitrouter.db
# Update all agent auth-profiles.json with the old EdDSA JWT
# Restart gateway

This only works if the old key's secret material is still intact and BitRouter v0.6.1 still accepts EdDSA algorithm tokens (unclear).

Related issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions