Wallet Standard Sign-In (SEP-0001)
How Kausa uses the Solana Wallet Standard Sign-In feature for phishing-resistant authentication.
What is SEP-0001?
SEP-0001 is the Solana Wallet Standard Sign-In feature (solana:signIn). It replaces the older approach of asking users to sign an arbitrary text message with a structured, domain-bound authentication flow.
When a wallet supports solana:signIn, it constructs a sign-in message internally and shows the requesting domain to the user. The wallet verifies the domain itself. If a phishing site at evil-clone.com requests sign-in for kausa.app, the wallet refuses before the user sees anything.
Why Kausa uses it
The previous hand-rolled SIWS flow relied on users reading the message text to confirm the domain. That works in theory, but most people sign without reading. SEP-0001 moves the domain check into the wallet UI so it happens automatically.
Kausa checks whether the connected wallet exposes the signIn feature. Phantom, Solflare, and Backpack all support it. Wallets that don't get the legacy flow instead. Either way, the session cookie is the same.
How it works
sequenceDiagram
participant User
participant Wallet
participant Client as Kausa Client
participant Server as Kausa Server
User->>Client: Click "Connect Wallet"
Client->>Wallet: Check for solana:signIn feature
alt Wallet supports SEP-0001
Client->>Server: GET /api/auth/siws/nonce
Server-->>Client: nonce
Client->>Wallet: signIn({ domain, nonce, chainId, ... })
Wallet->>User: Show structured sign-in panel
User->>Wallet: Approve
Wallet-->>Client: { signedMessage, signature, account }
Client->>Server: POST /api/auth/siws (type: "sep0001")
Server->>Server: Verify domain, chainId, nonce, expiry, ed25519 sig
Server-->>Client: Session cookie
else Legacy flow
Client->>Server: GET /api/auth/siws/nonce
Server-->>Client: nonce
Client->>Wallet: signMessage(text)
Wallet->>User: Show raw message
User->>Wallet: Approve
Wallet-->>Client: signature
Client->>Server: POST /api/auth/siws (type: "legacy")
Server->>Server: Verify nonce, expiry, ed25519 sig
Server-->>Client: Session cookie
endServer-side verification
The server checks five things for SEP-0001 payloads:
- Domain must match the production hostname or
localhost:3700in development. No wildcards, no regex. Literal string match only. - Chain ID must match the
SOLANA_NETWORKenvironment variable (devnetin current deployment). - Nonce must be server-issued and unused. Consumed on first use (single-use enforcement via the database).
- Expiration: the
expirationTimefield must be in the future. - Signature: Ed25519 over the signed message bytes, verified against the account's public key using
tweetnacl.
If any check fails, the request is rejected. The nonce gets consumed before the signature check, so a failed signature attempt still burns the nonce.
Rollback
To disable SEP-0001 and go back to legacy-only:
- Remove the
case "sep0001":branch insrc/app/api/auth/siws/route.ts. - Revert
src/components/wallet-button.tsxto always use thesignMessagepath.
Wallets fall back to the legacy flow automatically when SEP-0001 isn't offered. The session cookie format is identical, so users won't notice.