[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)
- Generate a challenge transaction signed by a server-owned "auth server" account
- Include a cryptographically random nonce (at least 32 bytes of entropy)
- Set
timeBounds with min = now - threshold and max = now + threshold (SEP-10 spec: threshold defaults to 300 seconds / 5 minutes)
- 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
- Validate that the transaction was signed by the correct auth server account
- Delete the used nonce from Redis (single-use)
- 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
[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:criticalRequirements
1. SEP-10 Challenge-Response Implementation
Implement the full SEP-10 authentication flow:
Challenge Phase (
POST /auth/challenge)timeBoundswithmin = now - thresholdandmax = now + threshold(SEP-10 spec: threshold defaults to 300 seconds / 5 minutes)Verify Phase (
POST /auth/verify)@stellar/stellar-sdktimeBoundswindow2. Clock Skew Tolerance
now - threshold > tx.timeBounds.minortx.timeBounds.max > now + threshold3. Network Resilience
503 Service Unavailableif Horizon is unreachable4. Network Awareness
testnetandmainnetnetwork passphrases5. Security Hardening
crypto.randomBytes()entropyCHALLENGE_TTL_SECONDS)6. Testing Requirements
@stellar/stellar-sdk— test challenge generation, signature verification, nonce lifecycle@nestjs/testingwith mocked Horizon responses for: