Overview
SIWX solves a key problem in x402: repeat access to purchased content. Without SIWX, clients must pay every time they request a resource. With SIWX:- For Buyers: Sign in with your wallet to access content you’ve already paid for
- For Sellers: Grant access to returning customers without requiring repayment
- Chain-Agnostic: Works with EVM (Ethereum, Base, etc.) and Solana wallets
- Standards-Based: Built on CAIP-122, EIP-4361 (SIWE), and Sign-In-With-Solana
How It Works
- Server returns 402 with
sign-in-with-xextension containing challenge parameters - Client signs the CAIP-122 message with their wallet
- Client sends signed proof in
SIGN-IN-WITH-XHTTP header - Server verifies signature and grants access if wallet has previous payment
Server Usage
Recommended: Hooks (Automatic)
The easiest way to implement SIWX is using the provided hooks, which handle all the complexity automatically:- TypeScript
- siwxResourceServerExtension: Derives
networkfromaccepts,domain/urifrom request URL, refreshesnonce/issuedAt/expirationTimeper request - createSIWxSettleHook: Records payment when settlement succeeds
- createSIWxRequestHook: Validates and verifies SIWX proofs, grants access if wallet has paid
Smart Wallet Support (EIP-1271 / EIP-6492)
By default, only EOA (Externally Owned Account) signatures are verified. To support smart contract wallets (like Coinbase Smart Wallet, Safe, etc.), passpublicClient.verifyMessage from viem:
- TypeScript
- EIP-1271: Verification of deployed smart contract wallets
- EIP-6492: Verification of counterfactual (not-yet-deployed) wallets
Manual Usage (Advanced)
For custom implementations, you can use the low-level functions directly:- TypeScript
Client Usage
Recommended: Client Hook (Automatic)
The easiest way to use SIWX as a client is with the provided hook:- TypeScript
- Detects SIWX support in 402 responses
- Matches your wallet’s chain with server’s
supportedChains - Signs and sends the authentication proof
- Falls back to payment if SIWX auth fails
Manual Usage (Advanced)
For custom implementations:- TypeScript
Multi-Chain Support
Servers can support multiple chains (e.g., both EVM and Solana) by including multiple entries insupportedChains:
- TypeScript
chainId against supportedChains and use the first matching entry. The same nonce is shared across all chains, preventing replay attacks when authenticating with different wallets.
Supported Chains
EVM (Ethereum, Base, Polygon, etc.)
- Chain ID Format:
eip155:*(e.g.,eip155:8453for Base) - Signature Type:
eip191 - Signature Schemes:
eip191(EOA - default)eip1271(smart contract wallet)eip6492(counterfactual wallet)
- Message Format: EIP-4361 (SIWE)
Solana
- Chain ID Format:
solana:*(e.g.,solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpfor mainnet) - Signature Type:
ed25519 - Signature Scheme:
siws - Message Format: Sign-In With Solana
API Reference
declareSIWxExtension(options?)
Creates the extension object for servers to include in PaymentRequired. Most fields are derived automatically from request context when using siwxResourceServerExtension.
parseSIWxHeader(header)
Parses a base64-encoded SIGN-IN-WITH-X header into a payload object.
validateSIWxMessage(payload, resourceUri, options?)
Validates message fields (expiry, domain binding, nonce, etc.).
verifySIWxSignature(payload, options?)
Verifies the cryptographic signature and recovers the signer address.
createSIWxPayload(serverInfo, signer)
Client helper that creates and signs a complete payload.
encodeSIWxHeader(payload)
Encodes a payload as base64 for the SIGN-IN-WITH-X header.
Storage Interface
ImplementSIWxStorage to track which wallets have paid:
InMemorySIWxStorage for development. For production, implement persistent storage (database, Redis, etc.).
Security Considerations
- Domain Binding: The
domainfield prevents signature reuse across different services - Nonce Uniqueness: Each challenge MUST have a unique nonce to prevent replay attacks
- Temporal Bounds: The
issuedAt,expirationTime, andnotBeforefields constrain signature validity windows - Chain-Specific Verification: Signatures are verified using chain-appropriate algorithms, preventing cross-chain signature reuse
- Smart Wallet Support: EIP-1271 and EIP-6492 verification requires an RPC call to the wallet contract
Troubleshooting
Signature Verification Fails
Problem:verifySIWxSignature returns valid: false.
Solutions:
- Ensure the message was signed with the correct wallet
- Check that the signature scheme matches the wallet type
- For smart wallets, enable
evmVerifieroption with a viem public client - Verify the chain ID matches between client and server
Message Validation Fails
Problem:validateSIWxMessage returns valid: false.
Solutions:
- Check that
issuedAtis recent (withinmaxAge, default 5 minutes) - Verify
expirationTimehasn’t passed - Ensure
domainmatches the server’s domain - Confirm
urimatches the resource URI
Client Hook Not Working
Problem: SIWX authentication not being attempted. Solutions:- Verify server is declaring SIWX extension in 402 response
- Check that client’s wallet chain matches one of the
supportedChains - Ensure signer is properly configured for the wallet type
Related Resources
- CAIP-122 Specification - Sign-In-With-X standard
- EIP-4361 (SIWE) - Sign-In With Ethereum
- Sign-In With Solana
- x402 Core Package
- Lifecycle Hooks - Custom payment flow logic