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:
✅ POST https://api.aveid.net/api/oauth/token
❌ POST https://aveid.net/api/oauth/token
Symptom: Token endpoint returns 400 invalid_request even though you’re sending the right values.Cause: Ave accepts both OAuth-standard snake_case fields and legacy camelCase fields. Problems usually come from mixing names incorrectly or misspelling them.Fix: Prefer the standard OAuth field names in new integrations:
{
  "grant_type": "authorization_code",
  "client_id": "YOUR_CLIENT_ID",
  "redirect_uri": "...",
  "code_verifier": "..."
}
Legacy grantType, clientId, redirectUri, and codeVerifier still work for backward compatibility.
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:
scope=openid profile email
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: Token exchange with grantType: urn:ietf:params:oauth:grant-type:token-exchange returns access_denied or invalid_target.Possible causes:
  • No active connector grant for this user
  • The target resource is disabled
  • Requested scope exceeds what the grant allows
  • subjectToken was issued to a different client than expected
Fix: Re-run the connector authorization flow (https://aveid.net/connect) with the correct resource and scope, making sure the source app’s token is used as subjectToken.
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:
const fixed = rawKey.replace(/ /g, "+");
const bytes = atob(fixed);
Always normalize base64 strings from URL fragments before decoding.
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 April 22, 2026