How Base Verify protects user data and ensures secure verification.
- Wallet addresses associated with verified provider accounts
- Provider account metadata (username, follower counts, verification status)
- OAuth tokens (encrypted, never shared with apps)
- Verification timestamps
- Your users' private keys
- Provider account passwords
- User activity or browsing history
- Any data beyond what's needed for verification
When you call /v1/base_verify_token, you receive:
Standard Response (200 OK):
{
"token": "abc123...",
"signature": "def456...",
"action": "base_verify_token",
"wallet": "0x1234..."
}No PII is returned
Every API call requires a valid SIWE signature from the wallet owner. This prevents:
- Arbitrary lookup of verification status
- Third parties checking if a wallet is verified
- Enumeration attacks
What is SIWE?
Sign-In with Ethereum lets the wallet owner prove control over their address by signing a structured message. Base Verify relies on it to ensure:
- Privacy protection – Only the wallet owner can ask about their verification status.
- Security – Requests come from the actual wallet, not a third party.
- Trait enforcement – The SIWE message encodes the trait requirements you set; Base Verify validates that the signed traits match what your backend expects.
Example SIWE payload
{
domain: "your-app.com",
address: "0x1234...", // User's wallet
chainId: 8453, // Base
resources: [
"urn:verify:provider:x", // Which provider
"urn:verify:provider:x:verified:eq:true", // Trait requirements
"urn:verify:action:base_verify_token" // What action
]
}The user signs this message, proving they control the wallet and agree to check those specific traits.
- OAuth access tokens are encrypted at rest
- Never exposed to your application
- Used only by Base Verify to refresh provider data
- Can be revoked by user at any time
Users can delete their verifications at any time:
- Removes all stored provider data
- Invalidates future token generation
- Your app's stored tokens become meaningless (user can't re-verify with same account)
How Base Verify validates provider accounts:
- User initiates OAuth in Base Verify Mini App
- Provider (X, Instagram, etc.) authenticates the user
- Provider returns OAuth token to Base Verify
- Base Verify fetches account data using OAuth token
- Base Verify stores verification linked to user's wallet
- OAuth token is encrypted and stored securely
Your app never handles OAuth tokens or redirects. This is all handled within the Base Verify Mini App.
Critical Security Requirement:
When your backend receives a SIWE message from the frontend, you MUST validate that the trait requirements in the message match what your backend expects. This prevents users from modifying trait requirements on the frontend to bypass your access controls.
Example Attack Without Validation:
- Your app requires users to have 100 followers
- User modifies the frontend to request only 10 followers
- User signs the modified message
- Without validation, your backend forwards the request to Base Verify
- User gains access with less than 100 followers ❌
Implementation:
import { validateTraits } from './lib/trait-validator';
// Define what traits your app requires
const expectedTraits = {
'followers': 'gte:100'
};
// Validate before forwarding to Base Verify
const validation = validateTraits(message, 'x', expectedTraits);
if (!validation.valid) {
return res.status(400).json({
error: 'Invalid trait requirements in message',
details: validation.error
});
}
// Now safe to forward to Base Verify APIKey Points:
- Trait requirements in SIWE message are embedded as URNs (e.g.,
urn:verify:provider:x:followers:gte:100) - Users can modify these before signing
- Backend must validate they match expected requirements
- Validation must happen before calling Base Verify API
Never:
- Include secret key in frontend code
- Use
NEXT_PUBLIC_*or similar environment variables that expose to browser - Commit secret keys to version control
- Share secret keys in chat, email, or documentation
Always:
- Store secret key in backend environment variables only
- Use
.envfiles that are gitignored - Rotate keys immediately if accidentally exposed
- Call Base Verify API only from your backend
Store verification tokens securely:
// In your database
{
token: "abc123...", // Unique per provider account
walletAddress: "0x1234...", // The wallet (for your records)
provider: "x", // Which provider
claimedAt: "2024-01-15" // When they verified
}Index by token to prevent duplicate claims across different wallets.
Cache verification results to reduce API calls:
- Cache for the user's session (not permanently)
- Clear cache when user disconnects wallet
- Don't check verification on every page load
Handle each response code appropriately:
- 200 → Grant access
- 404 → Redirect to Base Verify Mini App
- 400 (traits_not_satisfied) → Show user they don't meet requirements (don't retry)
- Integration Guide - Full implementation guide
- API Reference - Endpoint documentation
- Trait Catalog - Available traits