Skip to content

feat(auth): Implement SEP-10 Challenge-Response Authentication#20

Merged
oomokaro1 merged 8 commits into
OrbitStream:mainfrom
Queenode:main
Jun 19, 2026
Merged

feat(auth): Implement SEP-10 Challenge-Response Authentication#20
oomokaro1 merged 8 commits into
OrbitStream:mainfrom
Queenode:main

Conversation

@Queenode

@Queenode Queenode commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Closes #4

Detailed changes:

  • Created RedisService for secure nonce management with 5-minute TTLs.
  • Updated AuthService to handle complete SEP-10 Challenge and Verification lifecycle:
    • Generates 32-byte entropy nonces for challenge transactions.
    • Correctly applies network passphrases and auth server keys dynamically (Mainnet vs Testnet).
    • Validates single-use nonces via Redis.
    • Tolerates up to 60s of clock skew during timeBounds verification (logs at >30s).
  • Implemented robust network resilience for Horizon API queries:
    • Added strict 5s timeout limits on all account requests.
    • Implemented 2x exponential backoff retries (1s, 2s).
    • Added a Circuit Breaker that triggers a 30s pause after 3 consecutive errors.
  • Secured verification endpoint natively via Redis rate-limiting (max 10 attempts / wallet / minute).
  • Rewrote testing suite to thoroughly evaluate edge cases including mock Horizon API delays, expired transactions, invalid signatures, rate-limit thresholds, and circuit breaker activation, attaining >84% code coverage in auth.service.ts.

Queenode and others added 2 commits June 18, 2026 16:22
Detailed changes:
- Created RedisService for secure nonce management with 5-minute TTLs.
- Updated AuthService to handle complete SEP-10 Challenge and Verification lifecycle:
  - Generates 32-byte entropy nonces for challenge transactions.
  - Correctly applies network passphrases and auth server keys dynamically (Mainnet vs Testnet).
  - Validates single-use nonces via Redis.
  - Tolerates up to 60s of clock skew during timeBounds verification (logs at >30s).
- Implemented robust network resilience for Horizon API queries:
  - Added strict 5s timeout limits on all account requests.
  - Implemented 2x exponential backoff retries (1s, 2s).
  - Added a Circuit Breaker that triggers a 30s pause after 3 consecutive errors.
- Secured verification endpoint natively via Redis rate-limiting (max 10 attempts / wallet / minute).
- Rewrote testing suite to thoroughly evaluate edge cases including mock Horizon API delays, expired transactions, invalid signatures, rate-limit thresholds, and circuit breaker activation, attaining >84% code coverage in auth.service.ts.

Closes issue: [SEC] Implement SEP-10 Challenge-Response Authentication
- Auto-format auth.service.ts and auth.service.spec.ts with prettier
- Remove unused imports (BadRequestException, jwtService, redisService)
@oomokaro1

Copy link
Copy Markdown
Contributor

Hi @Queenode! Thanks for the SEP-10 implementation — the approach is solid. CI is failing due to lint errors. Here's how to fix:

1. Run prettier to auto-fix formatting:

npx prettier --write src/auth/auth.service.spec.ts src/auth/auth.service.ts

2. Fix unused variables in auth.service.spec.ts:

  • Remove BadRequestException from the import (line 2)
  • Remove let jwtService: JwtService; declaration (line 25)
  • Remove let redisService: RedisService; declaration (line 26)
  • Remove the assignment lines:
    jwtService = module.get<JwtService>(JwtService);
    redisService = module.get<RedisService>(RedisService);

After these changes, run npm run lint locally to verify before pushing.

@oomokaro1

Copy link
Copy Markdown
Contributor

Hi @Queenode! I compared your implementation against issue #4 requirements. Here's the full checklist:

Requirement Coverage

Requirement Status
Challenge Phase
Challenge transaction signed by server account
32 bytes random nonce (crypto.randomBytes)
timeBounds set (now ± threshold)
Nonce stored in Redis with TTL
Returns XDR-encoded transaction
Verify Phase
Accept & decode signed XDR
Verify signature against Stellar network
Validate nonce matches stored challenge
Validate timeBounds window
Validate server signature
Delete used nonce (single-use)
Issue JWT on success
Clock Skew Tolerance
60s tolerance
Warning at >30s
Reject outside tolerance
Network Resilience
Circuit breaker: 3 failures → 30s pause
5s timeout on Horizon calls
Retry 2x with backoff (1s, 2s)
Never skip verification
Network Awareness
Testnet + mainnet support
Different auth server accounts per network
Config-driven passphrases
Security Hardening
32 bytes entropy
Configurable TTL
Single-use nonce
Rate limiting (10/min)

Missing Test Scenarios

The issue explicitly requires these tests:

Test Status
Valid login flow (challenge → sign → verify → JWT)
Expired challenge
Already-used nonce ✅ (covered by expired test)
Wrong network passphrase ❌ Not tested
Forged signature ❌ Not tested
Horizon timeout → 503 ❌ Only 503 tested, not explicit timeout
Horizon rate limit → retry then fail
Clock skew edge cases (just within, just outside) ❌ Only expired tested
>80% code coverage ⚠️ Not verified

Code Issues

  1. Duplicate Redis clientsrc/auth/redis.service.ts uses the redis package, while PR feat: Redis-backed payment cursor with distributed lock and Horizon rate-limit backoff #21 adds src/redis/redis.service.ts using ioredis. These are two different Redis clients in the same app. Consider reusing the shared Redis module.

  2. Rate limiter counts all attempts, not just failurescheckRateLimit() increments on every verifyChallenge() call. After 10 successful rapid verifications, the counter resets on success (del), but successful calls temporarily increment the counter. Should only increment on failure.

  3. Math.max(NONCE_BYTES, 32) is redundantNONCE_BYTES is already 32.

  4. getServerKeypair() creates a new keypair on every call — The old code cached it in initializeServerKeypair(). Consider caching again to avoid repeated Keypoint.fromSecret() calls.

CI Status

CI was failing on lint (prettier formatting + unused vars). I pushed a fix commit earlier. Please verify the lint passes after pulling the latest.

Queenode added 2 commits June 19, 2026 06:54
- Add missing test scenarios (wrong passphrase, forged signature, clock skew, horizon timeout)
- Replace local RedisService with a shared ioredis module to resolve duplication
- Fix rate limiting to only increment counters on failure
- Remove redundant Math.max on nonce bytes
- Cache server keypair generation
@Queenode

Copy link
Copy Markdown
Contributor Author

thank you @oomokaro1 I've successfully addressed all the feedback points from the PR review

@oomokaro1

Copy link
Copy Markdown
Contributor

Hey @Queenode, thanks for the great work on this PR! I noticed a small issue in auth.module.ts — you're importing RedisModule from ../redis/redis.module, but that file doesn't exist. The RedisService is actually defined in ./redis.service.

Here's the fix:

src/auth/auth.module.ts:

  1. Change the import:
// Remove:
import { RedisModule } from '../redis/redis.module';

// Add:
import { RedisService } from './redis.service';
  1. Update providers:
// Change:
providers: [AuthService, JwtStrategy],

// To:
providers: [AuthService, JwtStrategy, RedisService],

Once you apply this change, CI should pass. Let me know if you have any questions!

@oomokaro1 oomokaro1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! This is a solid implementation of SEP-10 Challenge-Response authentication. Great work on the circuit breaker, rate limiting, and comprehensive test coverage.

@oomokaro1

Copy link
Copy Markdown
Contributor

Thanks for the awesome contribution @Queenode! This SEP-10 implementation is solid — great job on the circuit breaker, rate limiting, and thorough test coverage.

I'll handle the auth.module.ts Redis import fix and the branch protection config after merging. Merging now 🚀

@oomokaro1 oomokaro1 merged commit b94484c into OrbitStream:main Jun 19, 2026
1 check 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.

[SEC] Implement SEP-10 Challenge-Response Authentication

2 participants