Authentication Concepts
Authentication Concepts
The IBEx Wallet API supports 4 authentication modes, each creating a Safe Smart Contract Wallet with a different signer type.
Passkeys (default)
wallet=passkeys — The most secure mode.
The browser generates a WebAuthn key pair (ECDSA P-256). The public key is registered as the signer for a new Safe Smart Contract Wallet (ERC-4337). The private key never leaves the device — it's protected by the device's secure enclave and biometrics.
Flow:
GET /v1.2/auth/sign-up→ returnscredentialRequestOptions- Browser calls
navigator.credentials.create(options)→ user touches biometric POST /v1.2/auth/sign-upwith the credential → wallet created
KDF (PIN/Password)
wallet=kdf — For devices without biometric support.
The signer key is derived client-side using Argon2id from a user-chosen PIN or password. The server provides a random salt and KDF parameters. The server never sees the PIN — only the derived public key.
Flow:
GET /v1.2/auth/sign-up?wallet=kdf→ returns salt, KDF params, challenge- Client derives key from PIN + salt using Argon2id
- Client signs the challenge with derived key
POST /v1.2/auth/sign-upwith the signature → wallet created
Email (OTP + Encrypted Backup)
wallet=email — Email-first onboarding.
The server sends a 6-digit OTP (30s expiry) to the user's email. The client generates a key pair locally, encrypts the private key with a passphrase, and sends the encrypted blob to the server as a backup. The server never accesses the real key.
Flow:
GET /v1.2/auth/sign-up?wallet=email&email=user@example.com→ sends OTP, returns challenge- User enters OTP →
POST /email/recoverto verify - Client generates key pair, encrypts private key
POST /v1.2/auth/sign-upwith credential + encrypted backup → wallet created
EOA + EIP-7702
wallet=7702 — Upgrade an existing EOA to a Smart Account.
The user already has an Externally Owned Account (EOA) from MetaMask, WalletConnect, etc. By signing a SIWE-like challenge, they register their EOA as a signer and create an EIP-7702 delegation to SafeEIP7702Proxy.
Flow:
GET /v1.2/auth/sign-up?wallet=7702&address=0xCa33...→ returns SIWE challenge- User signs challenge with their wallet
POST /v1.2/auth/sign-upwith{ wallet: "7702", address, signature, nonce }→ delegation created- Client broadcasts EIP-7702 authorization transaction on-chain