Core concepts

Wallet login (SIWS)

udrive authenticates with Sign-In-With-Solana: your wallet signs a domain-bound, single-use message and the server verifies the ed25519 signature — no passwords, no key custody.

Why Sign-In-With-Solana

udrive never asks for a password or a private key. Instead you prove control of a wallet by signing a short message. The signature is an ed25519 proof that the holder of the secret key approved this exact text — verifiable by anyone, reversible by no one.

  • No passwords to leak, reset, or phish.
  • No blockchain transaction and no gas — signing a message is free and off-chain.
  • The message is bound to udrive.one, so a signature captured elsewhere can't be replayed here.

The login flow

  1. The browser asks the server for a fresh nonce bound to your public key.
  2. The app builds the canonical sign-in message and your wallet signs it.
  3. The signature, public key, nonce, and timestamp are posted back for verification.
  4. The server checks the signature, consumes the single-use nonce, and issues an httpOnly session cookie.

Note

Nonces are single-use and expire after 5 minutes. Consuming one is atomic, so a captured nonce can't be reused even within its window.

The signed message

The message is deterministic and human-readable. The domain line lets your wallet show you exactly which site you are authorizing.

sign-in message
udrive.one wants you to sign in with your Solana account:
7xKEh…Pu8Z

Sign in to udrive. This request will not trigger a blockchain transaction or cost any gas fees.

URI: https://udrive.one
Version: 1
Nonce: 3vQ9…kP
Issued At: 2026-06-25T18:04:11.000Z

Sessions

On success the server sets a signed JWT in an httpOnly, SameSite=Lax cookie (udrive_session), secure in production, valid for 7 days. The cookie is inaccessible to JavaScript, and every mutating request additionally checks same-origin as CSRF defense.

  • GET /api/auth/me returns the current account, or null when signed out.
  • POST /api/auth/logout clears the session cookie.

Doing it yourself

Any Solana wallet that can sign a message works. The raw exchange:

siws.tsTypeScript
import bs58 from "bs58";

// 1. Get a nonce for your wallet's public key.
const { nonce, issuedAt, message } = await fetch(
  `/api/auth/nonce?pubkey=${pubkey}`,
).then((r) => r.json());

// 2. Sign the returned message bytes with the wallet.
const encoded = new TextEncoder().encode(message);
const { signature } = await wallet.signMessage(encoded);

// 3. Verify server-side to mint a session cookie.
const res = await fetch("/api/auth/verify", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
    pubkey,
    nonce,
    issuedAt,
    signature: bs58.encode(signature),
  }),
});

Tip

The public key must be valid base58 / 32-byte ed25519, the signature 64 bytes — the server rejects anything malformed before touching the database.