diff --git a/README.md b/README.md index f333b54..c1548b0 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ TrustFlow Core is the backend API service that powers off-chain logic for the Tr ## ✨ Core Features -- πŸ” **JWT Authentication**: Secure wallet-based auth with guard middleware and JWT strategy. +- πŸ” **JWT Authentication with Wallet Signatures**: Secure wallet-based auth using Stellar signature verification. Users authenticate by signing a cryptographic challenge with their Freighter wallet, proving ownership without exposing private keys. - πŸ’Ό **Escrow Management**: Full CRUD API for escrow entities β€” creation, funding, milestone tracking. - 🌐 **Stellar Integration**: Native Horizon and Soroban RPC helpers for on-chain reads and writes. - πŸ”” **Webhook Engine**: Event-driven webhook dispatch with automatic retry logic. @@ -23,12 +23,14 @@ TrustFlow Core is the backend API service that powers off-chain logic for the Tr ``` backend/ β”œβ”€β”€ src/ -β”‚ β”œβ”€β”€ auth/ # JWT auth β€” controller, guard, service, strategy +β”‚ β”œβ”€β”€ auth/ # JWT auth β€” controller, guard, service, strategy, DTOs +β”‚ β”‚ β”œβ”€β”€ dto/ # Request/response DTOs for validation +β”‚ β”‚ └── auth.module.ts # Auth module configuration β”‚ β”œβ”€β”€ escrow/ # Escrow API β€” controller, service, DTOs, entity β”‚ β”œβ”€β”€ stellar/ # Stellar helpers β€” Horizon, Soroban, config, service β”‚ β”œβ”€β”€ webhook/ # Webhook dispatch β€” controller, service, retry helper β”‚ β”œβ”€β”€ monitoring/ # Health checks, metrics, Prometheus helpers -β”‚ └── index.js # App entry point +β”‚ └── main.ts # App entry point ``` --- @@ -37,8 +39,9 @@ backend/ ### Prerequisites -- Node.js >= 18 +- Node.js >= 20 - A Stellar RPC endpoint (testnet or mainnet) +- Freighter wallet (for client-side wallet signature testing) ### Installation @@ -98,6 +101,31 @@ Full guide: [API Documentation](backend/API_DOCUMENTATION.md) - **`POST /auth/verify`** β€” Verify wallet signature, returns JWT - JWT Guard protects all downstream routes. +#### Authentication Flow + +1. **Request Challenge**: Client requests a cryptographic challenge for their wallet address +2. **Sign Challenge**: User signs the challenge with their Freighter wallet +3. **Verify & Get Token**: Client sends the signature to verify and receive a JWT token +4. **Use Token**: Include JWT in Authorization header for authenticated requests + +#### Example Usage + +```bash +# 1. Get challenge +curl "http://localhost:3001/auth/challenge?address=GXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + +# 2. Sign challenge with Freighter wallet (client-side) + +# 3. Verify signature and get JWT +curl -X POST http://localhost:3001/auth/verify \ + -H "Content-Type: application/json" \ + -d '{"address":"G...","signature":"..."}' + +# 4. Use JWT for authenticated requests +curl http://localhost:3001/escrows \ + -H "Authorization: Bearer " +``` + ### Escrow (`/escrow`) - **`POST /escrow`** β€” Create a new escrow vault. @@ -122,9 +150,16 @@ Full guide: [API Documentation](backend/API_DOCUMENTATION.md) ## πŸ›‘οΈ Security -- All routes behind the `AuthGuard` require a valid JWT. -- Input validation via class-validator DTOs on all write endpoints. -- Environment secrets never logged or exposed in responses. +- **Wallet Signature Verification**: Uses @stellar/stellar-sdk for cryptographic signature verification +- **Challenge Expiration**: Challenges expire after 5 minutes to prevent replay attacks +- **One-Time Use**: Each challenge can only be used once +- **JWT Expiration**: Tokens expire after 24 hours +- **Address Validation**: Validates Stellar public key format (G-prefixed, 56 characters) +- **Input Validation**: Uses class-validator DTOs on all endpoints +- **Guard Middleware**: All protected routes require valid JWT via JwtAuthGuard +- **Environment Secrets**: Never logged or exposed in responses + +For detailed authentication implementation documentation, see [AUTH_IMPLEMENTATION.md](backend/src/auth/AUTH_IMPLEMENTATION.md). --- @@ -151,10 +186,13 @@ cd backend && ./scripts/ci-check.sh ## πŸ—ΊοΈ Roadmap +- [x] **JWT Authentication with Wallet Signatures**: Implemented Stellar signature verification - [ ] **GraphQL Layer**: Optional GraphQL gateway over REST endpoints. - [ ] **Rate Limiting**: Per-wallet throttling on auth and escrow routes. - [ ] **Event Sourcing**: Full audit log for all escrow state transitions. - [ ] **Multi-network Support**: Seamless mainnet/testnet switching via config. +- [ ] **Token Refresh**: Implement refresh token mechanism for better UX +- [ ] **Redis Integration**: Use Redis for distributed challenge storage --- @@ -173,6 +211,3 @@ _Securing the future of work, one transaction at a time._ ## πŸ“œ License MIT License. Copyright (c) 2026 TrustFlow Protocol. -test - -# Test - should be blocked diff --git a/backend/package-lock.json b/backend/package-lock.json index 1d880e0..4c9fa30 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -7179,9 +7179,9 @@ } }, "node_modules/pg-protocol": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.14.0.tgz", - "integrity": "sha512-n5taZ1kO3s9ngDTVxsEznOqCyToTgz0FLuPq0B33COy5pPpuWJpY3/2oRBVETuOgzdqRXfWpM9HIhp2LBBT1BA==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.15.0.tgz", + "integrity": "sha512-cq9sECI5s0+uPUXjbz8ioyPJni6RzsRib0US67i5IoTZKw8fNeYlVE7u8F4dG7vEJJtc5wdD1K189lCCUwqWTQ==", "license": "MIT" }, "node_modules/pg-types": { diff --git a/backend/src/auth/auth.service.ts b/backend/src/auth/auth.service.ts index 3c37a94..4ba4c30 100644 --- a/backend/src/auth/auth.service.ts +++ b/backend/src/auth/auth.service.ts @@ -47,11 +47,15 @@ export class AuthService { } generateToken(address: string): string { - const payload = Buffer.from(JSON.stringify({ address, iat: Date.now() })).toString('base64'); - const sig = crypto - .createHmac('sha256', process.env.JWT_SECRET || 'dev') - .update(payload) - .digest('base64'); - return `${payload}.${sig}`; + const payload = { address, sub: address }; + return this.jwtService.sign(payload); + } + + validateToken(token: string): any { + try { + return this.jwtService.verify(token); + } catch (error) { + throw new UnauthorizedException('Invalid token'); + } } }