Description
The app currently has no standardized server-side authentication; wallet connection is purely client-side and cannot be verified by backend API routes. Implementing SEP-0010 (Stellar Web Authentication) allows the server to issue a signed challenge, the client to sign it with Freighter, and the server to exchange the signed transaction for a session token — giving API routes a cryptographically verified identity.
Technical Context
Server-side challenge generation at src/app/api/auth/challenge/route.ts using @stellar/stellar-sdk's TransactionBuilder to produce a ManageData operation per the SEP-0010 spec. Client-side signing orchestrated in src/hooks/useSep10Auth.ts, which calls Freighter's signTransaction and POSTs the result to src/app/api/auth/token/route.ts for verification. The verified JWT is stored in an httpOnly cookie via next/headers cookies().set(). A src/lib/auth/withAuth.ts helper wraps API route handlers that require a verified session. Environment variables SEP10_SERVER_SIGNING_KEY and SEP10_HOME_DOMAIN are required.
Acceptance Criteria
Description
The app currently has no standardized server-side authentication; wallet connection is purely client-side and cannot be verified by backend API routes. Implementing SEP-0010 (Stellar Web Authentication) allows the server to issue a signed challenge, the client to sign it with Freighter, and the server to exchange the signed transaction for a session token — giving API routes a cryptographically verified identity.
Technical Context
Server-side challenge generation at
src/app/api/auth/challenge/route.tsusing@stellar/stellar-sdk'sTransactionBuilderto produce a ManageData operation per the SEP-0010 spec. Client-side signing orchestrated insrc/hooks/useSep10Auth.ts, which calls Freighter'ssignTransactionand POSTs the result tosrc/app/api/auth/token/route.tsfor verification. The verified JWT is stored in anhttpOnlycookie vianext/headerscookies().set(). Asrc/lib/auth/withAuth.tshelper wraps API route handlers that require a verified session. Environment variablesSEP10_SERVER_SIGNING_KEYandSEP10_HOME_DOMAINare required.Acceptance Criteria
GET /api/auth/challenge?account={publicKey}returns a base64-encoded unsigned SEP-0010 challenge transaction valid for 5 minutesPOST /api/auth/tokenverifies the signed transaction's source account matches the requested public key, then returns a signed JWT in anhttpOnlycookiewithAuthreturn401 Unauthorizedwhen the cookie is absent or the JWT is expireduseSep10Authhook drives the full challenge-sign-token flow and updates anisAuthenticatedboolean in the wallet context401responses and re-initiates the SEP-0010 flow without user intervention