> ## Documentation Index
> Fetch the complete documentation index at: https://docs.0xmonaco.com/llms.txt
> Use this file to discover all available pages before exploring further.

# AuthService

> Wallet and session authentication RPCs

Package: `monaco.api.auth`

Source: `protos/api/auth.proto`

Use `AuthService` to create wallet challenges, verify wallet signatures, refresh sessions, and revoke sessions.

```protobuf theme={null}
service AuthService {
  rpc Challenge(ChallengeRequest) returns (ChallengeResponse);
  rpc Verify(VerifyRequest) returns (VerifyResponse);
  rpc Refresh(RefreshRequest) returns (RefreshResponse);
  rpc Revoke(RevokeRequest) returns (RevokeResponse);
}
```

## Notes

* `Challenge` binds the ed25519 session public key into the wallet-signed message. The challenge is single-use and authorizes exactly one keypair, once. It lives 5 minutes, or 30 minutes on a deployment where contract-signature login is enabled, because a multisig has to collect owner approvals before it can answer — that window is uniform for every address rather than eligibility-specific, so this unauthenticated RPC cannot be used to probe which addresses hold a BuilderCodes payout bucket. Read `expires_at` rather than assuming either value.
* `Verify` opens the signed session. There is no access token — the session is the registered public key. `signature` carries whatever the wallet produced and is bounded at 8192 decoded bytes: anything longer is refused as `UNAUTHENTICATED` rather than forwarded to the chain. The bound is far above any realistic owner set, and EOA signatures never approach it.
* `VerifyResponse` carries two signup signals alongside `expires_at` and `user`. Both are scoped per `(wallet, application)` — identity is created per application, so a wallet already registered on another application still sees them on its first sign-in to a new one. `is_new_user` is true when this verify created the user row (the wallet's first sign-in to this application). `referral_applied` is true when a TraderCodes referral relationship was recorded on this verify — a valid, non-self TraderCode presented on that first sign-in resolved to a known referrer. Both are false on every returning verify for the application. Use `is_new_user` to gate first-time UX and `referral_applied` to confirm a referral landed.
* `Challenge` and `Verify` share one rate budget per client address — 60 requests/min sustained, burst 120 by default, on public ingress — and return `RESOURCE_EXHAUSTED` over it once enforcement is on. Enforcement is gated by `auth_rate_limit_enforced`, which defaults off; until it flips, an over-budget request is admitted with a warn log rather than rejected. Both figures are deployment defaults, overridden by `AUTH_RATE_LIMIT_PER_MINUTE` / `AUTH_RATE_LIMIT_BURST`, so treat the environment's own budget as authoritative. The check runs before the signature, so a throttled request is never an authentication failure.
* `Verify` returns `ALREADY_EXISTS` ("resource already exists") when the session public key it is asked to bind is already registered — the key is stored under a unique constraint, and the violation maps to that status. Do not retry with the same keypair: generate a fresh session keypair and start a new challenge. The high-level `login()` flow generates one per call, so this only reaches callers driving `Challenge` / `Verify` themselves.
* A deactivated signing account is refused with `PERMISSION_DENIED` and a `google.rpc.ErrorInfo` detail in domain `auth.0xmonaco.com` whose `reason` is `ACCOUNT_DEACTIVATED`, on `Verify` and on every signed RPC.
* Both RPCs also return `INVALID_ARGUMENT` for invalid request parameters (on `Verify`, that includes a nonce already used or expired), `PERMISSION_DENIED` when the origin is not allowed for this application, `NOT_FOUND` for an invalid `client_id` or nonce, and `INTERNAL` for a server-side failure.
* `Verify` returns `UNAVAILABLE` when contract-signature (EIP-1271) verification of an eligible address could not be completed: the chain did not answer, did not answer within the deadline, or the server was at its concurrent-verification capacity and declined to ask. It is retryable and is **not** a verdict on the signature — a rejected signature is `UNAUTHENTICATED`, and so is a wallet contract that rejects by reverting. An eligible address can see it even when it turns out to be an EOA, because the code lookup precedes the choice of verification path; addresses that are not eligible never reach the chain. A fourth trigger is unrelated to contract wallets: `Verify` reads private-beta feature-flag state before anything else, and a read that cannot be served surfaces as the same retryable `UNAVAILABLE`, for any address, ahead of any signature or eligibility work.
* Authenticated RPCs are signed per request over the prost-encoded body. See [authenticated gRPC](/reference/grpc#authenticate-requests) for the metadata names, canonical signing string, session expiry/refresh, and a runnable signed example, or [TypeScript authentication](/sdk/typescript/auth) for the same session-key model in the SDK.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.