Skip to content

[SEC] Implement SEP-10 Challenge-Response Authentication for Stellar Wallet Verification #33

Description

@Queenode

🔴 Priority: Critical
Difficulty: Hard
Estimated Effort: 3-4 days
Relevant Files: src/services/stellar.service.ts, src/controllers/bot.controller.ts, src/routes/bot.routes.ts
Labels: security, enhancement, priority:critical, stellar

Requirements

  1. SEP-10 Challenge-Response Implementation
    Implement the full SEP-10 authentication flow to cryptographically prove wallet ownership before any financial operation:

    • Challenge Phase (POST /auth/challenge)

      • Generate a challenge transaction signed by a server-owned "auth server" Stellar account
      • Include a cryptographically random nonce (at least 32 bytes of crypto.randomBytes() entropy)
      • Set timeBounds with min = now - threshold and max = now + threshold (threshold defaults to 300 seconds)
      • Store the nonce in Redis with a TTL matching the challenge expiry
      • Return the XDR-encoded challenge transaction to the client
    • Verify Phase (POST /auth/verify)

      • Accept the signed challenge transaction XDR from the client
      • Decode the XDR and extract the client's signature
      • Verify the signature against the Stellar network using @stellar/stellar-sdk
      • Validate that the nonce matches a stored, unused challenge
      • Validate that the challenge is within the timeBounds window
      • Delete the used nonce from Redis (single-use enforcement)
      • Link the verified Stellar public key to the user's Prisma User record
  2. Clock Skew Tolerance

    • Handle up to 60 seconds of clock skew between the server and the Stellar ledger
    • Log a warning if clock skew exceeds 30 seconds
    • Reject challenges where now - threshold > tx.timeBounds.min or tx.timeBounds.max > now + threshold
  3. Network Resilience

    • Circuit breaker pattern for Horizon API calls: if Horizon returns 5xx or times out 3 times consecutively, stop making requests for 30 seconds
    • Timeout handling: Horizon calls must timeout after 5 seconds. Return 503 Service Unavailable if Horizon is unreachable
    • Retry logic: Retry failed Horizon signature verification up to 2 times with exponential backoff (1s, 2s)
  4. Network Awareness

    • Support both testnet and mainnet network passphrases via config.STELLAR_NETWORK
    • The auth server account must be different for testnet vs mainnet
    • Network passphrase must come from config, not hardcoded
  5. Security Hardening

    • Challenge nonces must be at least 32 bytes of crypto.randomBytes() entropy
    • Nonces expire after 5 minutes (configurable via CHALLENGE_TTL_SECONDS)
    • Used nonces are deleted immediately after verification (single-use)
    • Failed verification attempts are logged with the attempting wallet address
    • Implement rate limiting on the verify endpoint: max 10 failed attempts per wallet per minute
  6. Testing Requirements

    • Unit tests: Mock @stellar/stellar-sdk — test challenge generation, signature verification, nonce lifecycle
    • Integration tests using supertest with mocked Horizon responses for:
      • Valid login flow (challenge → sign → verify → link wallet)
      • Expired challenge (should reject)
      • Already-used nonce (should reject)
      • Wrong network passphrase (should reject)
      • Forged signature (should reject)
      • Horizon timeout (should return 503)
    • Target: >80% code coverage on auth module

Metadata

Metadata

Assignees

No one assigned

    Labels

    GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions