Need auth before you register an app? Start with Quick Ave. Come back here when you need refresh tokens, app branding, configured redirect URIs, or a confidential client.
Start with the embed flow
For most web apps, open Ave from your sign-in button and let the embed choose the best browser surface.startAveAuth() opens the Ave sheet first, escalates to a popup when a top-level browser context is required, and falls back to a redirect when popups are blocked. Omit clientId to use Quick Ave.
Prerequisites
Create an app in the developer portal
Go to devs.aveid.net and create an OAuth app. You’ll receive:
- Client ID — used in all requests; safe to include in browser code
- Client secret — server-side only; never put this in browser or mobile code
Register your redirect URI
Add the exact callback URL where Ave should redirect after login (e.g.
https://yourapp.com/callback). The URI must match exactly — no wildcards, no trailing-slash differences.For local development, enable development mode on the app to allow localhost, loopback, and Expo Go callback URLs without registering every port. Keep production callbacks registered explicitly.Login flow
Generate PKCE parameters and redirect the user
Before redirecting, generate PKCE parameters. They prove that the same browser session that started login is the one completing it.
state prevents CSRF attacks — without it, an attacker can trick your app into completing a login they started. nonce prevents replay attacks against the ID token. Both are random strings you generate and store temporarily.Handle the callback
Ave redirects to your
redirect_uri with ?code=AUTH_CODE&state=YOUR_STATE. Validate state before doing anything else.Understand the token response
A successful exchange returns:Ave returns tokens with different purposes:
| Token | Format | aud claim | Use for |
|---|---|---|---|
access_token | Opaque string | — | Calling Ave’s /api/oauth/userinfo |
access_token_jwt | Signed JWT | https://aveid.net | Ave APIs that accept JWTs, Connector delegation |
id_token | Signed OIDC JWT | Your client ID | User session, Convex auth |
refresh_token | Opaque string | — | Getting new tokens without re-login |
id_token and access_token_jwt are both signed JWTs with different audiences. The id_token audience is your clientId. The access_token_jwt audience is https://aveid.net. This matters for Convex and any library that validates JWT audience.id_token is only returned when you request the openid scope. refresh_token is only returned with offline_access.Refresh tokens
When the access token expires, exchange the refresh token for a new set without re-authenticating the user.Error reference
invalid_client
invalid_client
Client ID or client secret doesn’t match any registered app.
invalid_grant
invalid_grant
The code or refresh token is bad, expired, or was already used. For refresh tokens, this may also mean reuse detection triggered.
invalid_request
invalid_request
A required field is missing. Common cause: forgetting
codeVerifier when PKCE is required.invalid_scope
invalid_scope
A requested scope isn’t allowed for this app. Check your app’s scope allowlist in the developer portal.
invalid_target
invalid_target
The Connector
requestedResource key doesn’t exist or isn’t active.access_denied
access_denied
The Connector grant is missing or was revoked. Re-run the Connector authorization flow.
Next steps
Token details
JWT payload reference for
id_token and access_token_jwt, validation steps, and refresh token rotation.PKCE deep dive
PKCE security model, browser storage guidance, and anti-patterns to avoid.
Convex auth
Exactly how to wire Ave tokens into Convex, including which token to use and why.
Scopes and claims
Complete scope catalog with the exact JWT claims each scope adds.
