← Protocols
Stytch
Wallet / Auth·EVM · Solana

Stytch

01Description

Auth platform with first-class crypto wallet login alongside email magic links, passkeys, OAuth, SSO, and SCIM. Supports Sign-In with Ethereum (SIWE) for EVM wallets and message-signing flows for Solana wallets.

02Best for
  • 01Web2 + Web3 hybrid auth
  • 02SIWE with phishing-resistant domain binding
  • 03passkeys + crypto wallet in one session
  • 04B2B apps needing SSO + wallet login
  • 05drop-in UI for wallet auth
03Install
  • pnpm add @stytch/nextjs @stytch/vanilla-js
  • pnpm add stytch
04Environment variables
VariableScopeDescription
NEXT_PUBLIC_STYTCH_PUBLIC_TOKENClientStytch frontend public token from the Stytch dashboard. Client-safe.
STYTCH_PROJECT_IDServerStytch project ID (e.g. `project-live-...`). Server-only.
STYTCH_SECRETServerStytch project secret used by the Node SDK to call the backend API. Server-only.
05Prompt snippet
Use Stytch for crypto-wallet auth alongside email/passkey login. On the client, call `stytch.cryptoWallets.authenticateStart({ crypto_wallet_type: 'ethereum', crypto_wallet_address: address, siwe_params: { domain, statement, uri } })` to receive a SIWE-formatted challenge, ask the connected wallet to sign it (e.g. `walletClient.signMessage` from viem), then call `stytch.cryptoWallets.authenticate({ crypto_wallet_address, signature })` to exchange the signature for a Stytch session token. Wrap the Next.js app in `<StytchProvider stytch={createStytchUIClient(token)}>` and gate routes via `useStytchUser()` / `useStytchSession()`. On the server, verify the session JWT with `stytch.sessions.authenticateJwtLocal(jwt)` from the `stytch` Node SDK before trusting any `crypto_wallet_address` claim.
06Gotchas
  • `siwe_params` are required for Ethereum flows that use Sign-In with Ethereum — omitting them falls back to plain message signing without domain binding, defeating the anti-phishing guarantee.
  • Solana wallets use a different `crypto_wallet_type: 'solana'` and a different signing path (ed25519 over the raw challenge bytes) — passing `siwe_params` on a Solana flow throws a 400.
  • The frontend SDK exposes a session token, but server routes must call `authenticateJwtLocal` (or `sessions.authenticate` for revocation checks) — never trust the address embedded in the JWT until the signature is locally verified.
  • Stytch sessions roll over: the JWT in localStorage may be older than the live session — refresh it via `stytch.session.authenticate({ session_duration_minutes })` on app focus or downstream calls will 401 intermittently.
  • Stytch B2B and Consumer projects are separate — an SDK token for a Consumer project will silently fail against B2B endpoints (and vice-versa); pick one project type per app.
07Alternatives