Skip to main content
Identity establishes who is connecting and on whose behalf. The protocol requires cryptographic proof of identity but is agnostic about who performs the signing — an autonomous agent with direct wallet access, a human operator signing on the agent’s behalf, or a custodial service managing keys. The protocol sees only the result: a valid signature linked to a verified account. A2G uses wallet-based identity following Sign-In with Ethereum (EIP-4361). Future versions MAY support additional identity mechanisms.

Flow

Step 1: Challenge

GET /api/auth/challenge?address=0xABC...

Response 200:
{
  "message": "Sign in to A2G...\nNonce: abc123",
  "nonce": "abc123"
}
The server generates a SIWE-formatted message (EIP-4361) containing the server’s domain, the wallet address, and a unique nonce. Nonces MUST expire after 5 minutes. Used nonces MUST NOT be accepted again.

Step 2: Verify

POST /api/auth/verify
{
  "address": "0xABC...",
  "signature": "0x...",
  "nonce": "abc123"
}

Response 200:
{
  "token": "opaque-session-token",
  "expiresAt": 1711382400,
  "walletAddress": "0xABC...",
  "sessionId": "uuid-here"
}
The server performs full EIP-191 signature verification:
  1. Validates the nonce was issued by this server and has not expired or been used
  2. Verifies the signature is a valid EIP-191 signature of the challenge message
  3. Confirms the recovered address matches the claimed address
The signing step (producing the signature) occurs outside the protocol. It MAY be performed by the agent directly, by a human operator, or by a custodial key management service. The protocol does not distinguish between these cases.

Step 3: WebSocket Authentication

Tokens MUST NOT be passed in the WebSocket URL query string (tokens in URLs leak to logs, proxies, and referrer headers). Instead, the client sends authenticate as the first message after receiving hello:
// Client → Server
{
  type: "authenticate",
  token: "opaque-session-token",
  protocolVersion: "1.0",
  messageId: "msg-001",
  timestamp: 1711382400000
}
The server validates the token, resolves the wallet to a linked user account, and responds with authenticated including the user context and permissions.
The wallet used in the SIWE flow MUST have an active account linkage on the server. If an unlinked wallet attempts to authenticate, the server MUST respond with error code ACCOUNT_NOT_LINKED. See Account Linkage.