Skip to content

[SEC] Implement SEP-10 Challenge-Response Authentication #4

Description

@oomokaro1

[SEC] Implement SEP-10 Challenge-Response Authentication

🔴 Priority: Critical

Difficulty: Hard
Estimated Effort: 2-3 days
Relevant Packages: OrbitStream_backend/, orbitstream_docs/
Labels: security, enhancement, priority:critical

Requirements

1. SEP-10 Challenge-Response Implementation

Implement the full SEP-10 authentication flow:

Challenge Phase (POST /auth/challenge)

  1. Generate a challenge transaction signed by a server-owned "auth server" account
  2. Include a cryptographically random nonce (at least 32 bytes of entropy)
  3. Set timeBounds with min = now - threshold and max = now + threshold (SEP-10 spec: threshold defaults to 300 seconds / 5 minutes)
  4. Store the nonce in Redis with a TTL matching the challenge expiry
  5. Return the XDR-encoded challenge transaction to the client

Verify Phase (POST /auth/verify)

  1. Accept the signed challenge transaction XDR from the client
  2. Decode the XDR and extract the client's signature
  3. Verify the signature against the Stellar network using @stellar/stellar-sdk
  4. Validate that the nonce matches a stored, unused challenge
  5. Validate that the challenge is within the timeBounds window
  6. Validate that the transaction was signed by the correct auth server account
  7. Delete the used nonce from Redis (single-use)
  8. Issue a JWT on success

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)
  • Graceful degradation: If Horizon is temporarily unavailable, reject login with a clear error — never skip verification

4. Network Awareness

  • Support both testnet and mainnet network passphrases
  • 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: Use @nestjs/testing with mocked Horizon responses for:
    • Valid login flow (challenge → sign → verify → JWT)
    • Expired challenge (should reject)
    • Already-used nonce (should reject)
    • Wrong network passphrase (should reject)
    • Forged signature (should reject)
    • Horizon timeout (should return 503)
    • Horizon rate limit (should retry then fail)
    • Clock skew edge cases (just within tolerance, just outside)
  • Load tests: Verify rate limiting works under concurrent requests
  • Target: >80% code coverage on auth module

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions