Skip to main content
Symptom: Token requests fail or return an unexpected error page.Cause: Sending API requests to aveid.net instead of api.aveid.net.Fix:
Symptom: Token endpoint returns 400 invalid_request even though you’re sending the right values.Cause: A required field is missing or misspelled. The error_description names the fields Ave couldn’t read. Ave accepts OAuth snake_case names and their camelCase equivalents, in a form-encoded or JSON body.Fix:
Symptom: Token exchange returns invalid_grant.Causes:
  • Base64url encoding bug in the verifier
  • Stored verifier was overwritten before exchange (e.g. user opened a second tab)
  • Multiple concurrent login flows racing
Fix: Generate one verifier per login intent, store it in sessionStorage, and clear it immediately after a single use.
Symptom: Token response has access_token but no id_token.Cause: The openid scope was not requested or was not granted for your app.Fix: Add openid to your requested scopes:
Symptom: A refresh request that previously worked now returns invalid_grant.Possible causes:
  • Token expired (refresh tokens have a maximum lifetime)
  • Token was revoked by the user or by the server
  • Reuse detection triggered — you sent the same refresh token twice (rotation means the old one is immediately invalidated after first use)
Fix: Treat invalid_grant on a refresh as a terminal session loss for that session and re-authenticate the user. Store the new refresh token returned by every successful refresh immediately. Ave only invalidates the rotated token lineage that was reused, so unrelated sessions on other devices should stay signed in.
Symptom: atob() throws, or the decrypted key is garbage.Cause: The app key is delivered via URL fragment (#app_key=...). Browsers silently replace + with a space in fragment parameters, breaking base64 decoding.Fix:
Always normalize base64 strings from URL fragments before decoding.
Symptom: Sign-in succeeds, but app_key or app_private_key is missing.Possible causes:
  • The sign-in did not request e2ee:symmetric or e2ee:asymmetric
  • The code was exchanged without reading the fragment, for example on a server callback route
  • The fragment was stripped by a router or redirect before the SDK read it
Fix: Request the encryption scope on every sign-in, and read the callback with completeOAuthCallback, the embed’s onTokens, or mergeAppEncryptionFromUrl in client code before anything rewrites the URL.
Symptom: Ciphertext written earlier fails to decrypt with the key from a new sign-in.Possible causes:
  • The user signed in with a different identity, which has different keys
  • A sign-in requested e2ee:reset, which rotated the keys
  • The user disconnected your app in Ave, which deleted its keys, and then signed in again
Fix: Scope stored data by identity ID. After a rotation, use the *_old keys delivered with the new ones to re-encrypt. If a trusted session still holds the original key, see Recover an app key. Never overwrite ciphertext you could not decrypt.
Symptom: Display name, avatar, or email shown in your app is outdated.Cause: Profile data cached from the initial token exchange is never refreshed.Fix: Re-fetch the profile from /api/oauth/userinfo on each login, or when you need fresh data.
Symptom: One user can see another user’s data, or data is missing after a user changes identity.Cause: App is storing data keyed by handle (username) instead of identityId. Handles can change; identityId is stable.Fix: Always key user data by the sub claim from the JWT (which is the identityId). Never rely on handle as a stable identifier.
Last modified on September 28, 2026