Mobile wallet security
Threat model and mitigations for connecting Solana wallets to Kausa from a mobile device.
This page explains how Kausa protects users who connect wallets from mobile devices.
How mobile wallet connection works
When you use Kausa on a mobile phone, your wallet app (Phantom, Solflare) communicates with the website through one of two channels:
- In-app browser — the wallet app opens Kausa inside its own browser. This is the most secure path because the wallet controls the entire browsing session.
- Deep links — the mobile browser sends you to the wallet app to approve a connection, then brings you back. This works but carries some risks (see below).
Kausa detects which environment you are in and recommends the safest option.
Ed25519 signature pairing
Every wallet connection on Solana uses Ed25519 cryptography. When you sign in:
- Kausa generates a one-time challenge (nonce) tied to the production domain.
- Your wallet signs that challenge with your private key (which never leaves the device).
- Kausa verifies the signature against your public key using
tweetnacl.
This happens identically on mobile and desktop. The signature proves you control the wallet without exposing any secrets.
Deep-link spoofing risks
On mobile, a malicious app could register the same deep-link scheme as a legitimate wallet (e.g., phantom://). If a user taps a deep link, the wrong app might intercept it.
How Kausa mitigates this
Kausa uses five mitigations against deep-link spoofing:
HMAC deep-link challenge. Every mobile deep-link includes a signed, session-bound token (?c=<token>) with a 2-minute TTL. The server verifies the HMAC before accepting sign-in, blocking tokens forged by intercepting apps. Single-use consumption prevents replay.
User-Agent validation. The server checks that the User-Agent string contains the expected in-app browser marker (Phantom or Solflare). On the client, the validator also confirms the wallet's global API object exists (window.solana.signIn or window.solflare.signAndSendTransaction). Mismatches throw a WalletIntegrityError.
Origin nonce. The mobile connect dialog displays a random 6-character hex code (formatted XXX-XXX) that users can compare between their browser and the wallet app to visually confirm they reached the correct site.
iOS Universal Links and Android App Links. Kausa publishes /.well-known/apple-app-site-association and /.well-known/assetlinks.json so iOS and Android can verify that deep links target the legitimate Phantom and Solflare apps. These files are served with Content-Type: application/json and a 1-hour cache.
Wallet continuity check. The session JWT stores the wallet address used at first sign-in (firstWallet). Before confirming a donation, the server verifies the transaction signer matches that original address. A mismatch returns 403. This stops attackers from swapping the connected wallet mid-session.
What users should do
- Open Kausa from the wallet app's built-in browser when possible.
- If using an external browser, check that the verification code in the connect dialog matches what you see in the wallet.
- Never approve sign-in requests you did not initiate.
Why the in-app browser is the recommended path
Phantom's in-app browser runs a full web view inside the wallet app. This gives you:
- Direct access to the wallet's signing interface without deep-link handoffs.
- Protection against deep-link hijacking by malicious apps.
- Consistent behavior across iOS and Android.
When Kausa detects a mobile user outside the in-app browser, it shows a hint banner explaining how to switch.
Mobile Wallet Adapter (MWA)
On Android, the Solana Mobile Wallet Adapter protocol provides a Bluetooth-based pairing channel between browser and wallet. MWA uses its own Ed25519 keypair for session-level encryption, separate from your Solana wallet keys.
Kausa supports MWA through the Wallet Standard discovery mechanism. When a wallet advertises MWA support, the framework-kit connection layer uses it automatically.
Platform-specific notes
iOS Safari
iOS does not support MWA. Wallet connection works through universal links or the in-app browser. Kausa detects iOS and shows an "Open in Phantom" CTA that uses the https://phantom.app/ul/browse/ universal link.
Android Chrome
Android supports both deep links and MWA. The Wallet Standard autoDiscover() picks up MWA-enabled wallets first. If no MWA wallet is found, Kausa falls back to deep-link CTAs.
Server-side protections (always active)
Regardless of which mobile path is used, Kausa's server-side protections apply:
- Ed25519 signature verification on every sign-in (
nacl.sign.detached.verify). - Single-use nonces stored in the database with 5-minute expiry.
- Domain allowlist (production hostname plus
localhost:3700in development). - Rate limiting on the SIWS endpoint (5 requests per minute per IP).
- Session cookies are
httpOnly,secure, andsameSite: lax.