zkLogin
zkLogin gives a user a self-custodial Sui address from an OAuth login. There is no seed phrase and no browser extension. Inodra runs the two services that zkLogin needs: the salt service and the prover.
New here? First zkLogin transaction in 6 steps.
How it works
- Your app makes an ephemeral key pair and puts a nonce in the OAuth request.
- The user signs in with Google, Apple, Twitch, or Facebook. Your app gets a JWT.
POST /v1/zklogin/addressreturns the user's Sui address. Inodra derives the salt.POST /v1/zklogin/provereturns a zero-knowledge proof for the session.- The ephemeral key signs transactions. The proof makes each signature valid for the address until
maxEpochpasses.
Inodra never holds a user key. See Security.
Setup checklist
- Register an OAuth client with your provider. Note the client ID.
- Open zkLogin in the dashboard and add the client ID. Add one entry for each client ID your app uses.
- Under API keys, create a key with the zkLogin scope. See API Key Scopes.
- For a key that ships in a browser:
- Give it only the zkLogin scope.
- Set allowed origins.
- Set a per-IP rate limit.
- Follow the Quickstart.
A request with a JWT audience that is not on your list gets 403 AUDIENCE_NOT_ALLOWED.
The client ID rule
The address depends on the client ID. The client ID is the
audclaim of the JWT. A different client ID gives a different address for the same user.
- Google and Apple issue a different client ID for each platform: web, iOS, Android.
- Use one shared client ID on all platforms. If you do not, the same user gets a different address on each platform.
- If you change or rotate the client ID later, every address changes.
- If you remove a client ID from the dashboard list, logins with it stop. Addresses never change.
The address also depends on your Inodra organization. See How salts work.
Supported providers
| Provider | Issuer (iss) |
|---|---|
https://accounts.google.com | |
| Apple | https://appleid.apple.com |
| Twitch | https://id.twitch.tv/oauth2 |
https://www.facebook.com |
A JWT from another issuer gets 400 UNSUPPORTED_ISSUER.
Networks
Mainnet and testnet. Devnet returns 400 NETWORK_NOT_SUPPORTED.
Base URLs: https://mainnet-api.inodra.com and https://testnet-api.inodra.com. The key's network selects the network.
- An API key belongs to a project, and a project has one network. A new organization's default project is on mainnet.
- Prove checks
maxEpochagainst the epoch of the key's network. Read the epoch from that same network. - The address does not depend on the network. A user has the same address on mainnet and testnet.
Pricing
| Method | Path | Credits | Purpose |
|---|---|---|---|
| POST | /v1/zklogin/nonce | 1 | Nonce, randomness, and maxEpoch |
| POST | /v1/zklogin/address | 2 | Salt and address for a JWT |
| POST | /v1/zklogin/prove | 50 | Zero-knowledge proof, in about 3 seconds |
- zkLogin needs a paid plan. On the Free plan both endpoints return
403 PLAN_REQUIRED. - Get one proof for each session. Use it for every transaction until
maxEpochpasses. - A failed request costs at most 2 credits, never 50. Responses with status
5xxand429are not charged. See Billing.
Proof rate caps
zkLogin is available on paid plans. Each organization has a cap on proofs per minute:
| Plan | Proofs per minute |
|---|---|
| Team | 20 |
| Growth | 60 |
| Professional | 120 |
| Business | 300 |
| Enterprise | Unlimited |
Over the cap, prove returns 429 PROOF_RATE_LIMITED with a Retry-After header.
Gasless transactions
zkLogin signatures work with the Fuel Station. A new user can transact with no SUI. See step 6 of the Quickstart.
Next steps
- Quickstart - login to signed transaction, with code
- API reference - both endpoints, all fields, all errors
- Security - salts, the enclave, and what we can and cannot see
- FAQ