Skip to main content
Pylon ships a complete EIP-4361 (Sign-In With Ethereum) implementation in the binary. Users prove ownership of their Ethereum address by signing a structured message; Pylon recovers the address from the signature and mints a session. No Magic.link, no WalletConnect server, no third-party SIWE service.

What it does

  1. Frontend asks Pylon for a fresh nonce for the user’s address.
  2. Frontend builds an EIP-4361 message (Sign in to acme.com\n\nAddress: 0x...\n...nonce: ...\n...) and asks the user’s wallet to sign it via personal_sign.
  3. Pylon recovers the address from the signature using secp256k1 ECDSA + Keccak-256 (Ethereum’s variant), validates the message’s domain + nonce + expiry, and mints a session keyed on the wallet.

Endpoints

Schema

The user entity needs a walletAddress field:
unique so two accounts can’t claim the same address.

Sign-in flow

1. Request a nonce

Response:
The nonce is bound to the address — using a nonce minted for one address against a different address fails verify. Single-use, short-lived. Errors:

2. Build + sign the message

The frontend constructs an EIP-4361 message and asks the wallet to sign it (MetaMask, WalletConnect, Coinbase Wallet, etc.):

3. Verify

Response on success:
displayName is optional — used only when Pylon creates a new User row for a first-time address. Default is the short-form 0x742d…beb0. Errors:

Verification details

Pylon validates:
  • Signature recovery — secp256k1 ECDSA + Keccak-256 hash of the EIP-191 prefix (\x19Ethereum Signed Message:\n<len> + message) recovers a 20-byte address. Must match message.address case-insensitively.
  • Nonce — must exist in the nonce store, must be bound to message.address, single-use (consumed on first verify).
  • Domainmessage.domain must match the request’s Host header. Prevents replay across deployments.
  • Issued / expiration — if message.expirationTime is set, must be in the future. If message.notBefore is set, must be in the past.
The recovered address is lowercased before lookup and storage so checksummed 0x742d35Cc... and lowercase 0x742d35cc... collapse to the same User row.

Security guarantees

  • secp256k1 + Keccak-256 via the k256 crate — same primitives Ethereum uses, audited.
  • Nonce binding to address — using nonce-for-A to sign-in-as-B fails verify.
  • Single-use nonces — consumed on first verify regardless of success.
  • Domain pinningmessage.domain validated against Host header; replay across deployments rejected.
  • Expiration enforcementexpirationTime and notBefore honored.
  • EIP-191 prefix properly applied — defeats signature reuse from any other Ethereum-signed payload.

Where to go next

  • Sessions — what /siwe/verify mints
  • OAuth — other identity providers for the same user (link multiple sign-in methods to one account)