This document describes the design for binding a Stellar wallet address to a LiquiFact user account and how this binding is used to authorize SME-specific API operations.
LiquiFact uses a dual-authentication model for SMEs:
- Standard Auth: JWT-based session for general API access (Login/Password or SSO).
- Wallet Binding: A verified link between the user account and a Stellar public key. This is required for operations that interact with on-chain escrows or sensitive SME invoice data.
The binding is established using Sign-In with Stellar (SIWS):
- Challenge: The backend provides a randomly generated challenge (nonce) to the frontend.
- Signature: The user signs the challenge using their Stellar wallet (e.g., Freighter, Albedo).
- Verification: The backend verifies the signature against the provided public key.
- Association: Once verified, the Stellar public key is stored in the user's profile in the database.
The authorizeSmeWallet middleware ensures that:
- The user is authenticated via JWT.
- The user has a bound wallet address (either in their profile or provided via stub headers).
The verifyInvoiceOwner middleware ensures that:
- The requested invoice belongs to the authenticated user (via
ownerId) or their bound wallet (viasmeWallet).
Retrieves a specific invoice for an SME, ensuring they own it via their wallet binding.
Request:
curl -X GET http://localhost:3001/api/sme/invoice/inv_123 \
-H "Authorization: Bearer <JWT_TOKEN>" \
-H "x-stellar-address: GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"Successful Response (200 OK):
{
"data": {
"id": "inv_123",
"amount": 5000,
"customer": "Acme Corp",
"status": "pending_verification",
"smeWallet": "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
},
"message": "Invoice retrieved successfully via wallet verification."
}Error: Wallet Not Bound (403 Forbidden):
{
"error": {
"code": "WALLET_UNBOUND",
"message": "No Stellar wallet address is bound to this account.",
"correlation_id": "req_..."
}
}- Input Validation: All wallet addresses are validated against Stellar's
G...public key format. - Replay Protection: Live SIWS implementation must use one-time nonces to prevent signature replay attacks.
- Privacy: Only public keys are stored; private keys never leave the user's wallet.