benweet/stackedit · error · Error
Client ID inconsistent.
Error message
Client ID inconsistent.
What it means
Google's OAuth2 ID token contains an 'aud' (audience) claim that must equal the OAuth client ID that requested it. startOauth2 validates body.aud against clientId and throws 'Client ID inconsistent.' when they differ, defending against tokens minted for a different OAuth client being accepted.
Source
Thrown at src/services/providers/helpers/googleHelper.js:142
login_hint: sub,
prompt: silent ? 'none' : null,
nonce: utils.uid(),
},
silent,
);
// Call the token info endpoint
const { body } = await networkSvc.request({
method: 'POST',
url: 'https://www.googleapis.com/oauth2/v3/tokeninfo',
params: {
access_token: accessToken,
},
}, true);
// Check the returned client ID consistency
if (body.aud !== clientId) {
throw new Error('Client ID inconsistent.');
}
// Check the returned sub consistency
if (sub && `${body.sub}` !== sub) {
throw new Error('Google account ID not expected.');
}
// Build token object including scopes and sub
const existingToken = store.getters['data/googleTokensBySub'][body.sub];
const token = {
scopes,
accessToken,
expiresOn: Date.now() + (expiresIn * 1000),
idToken,
sub: body.sub,
name: (existingToken || {}).name || 'Someone',
isLogin: !store.getters['workspace/mainWorkspaceToken'] &&
scopes.includes('https://www.googleapis.com/auth/drive.appdata'),
isSponsor: false,View on GitHub (pinned to 6dce2a5e36)
Solutions
- Ensure the clientId passed to startOauth2 exactly matches the client ID used to create the auth request (same Google Cloud project, no trailing/leading whitespace).
- Discard old tokens and re-run the full sign-in flow with the correct client ID.
- Check environment config (env vars/build constants) so staging and prod use their own client IDs consistently.
- If you migrated Google Cloud projects, re-issue tokens under the new client and invalidate stored ones.
Example fix
// before const token = await googleHelper.startOauth2(code, sub, clientIdFromOldConfig); // after const token = await googleHelper.startOauth2(code, sub, constants.googleClientId); // same ID used in the auth URL
Defensive patterns
Strategy: validation
Validate before calling
const GOOGLE_CLIENT_ID = process.env.GOOGLE_CLIENT_ID;
if (!GOOGLE_CLIENT_ID || !/^[0-9a-zA-Z-]+\.apps\.googleusercontent\.com$/.test(GOOGLE_CLIENT_ID)) {
throw new Error('GOOGLE_CLIENT_ID missing or malformed');
}
if (GOOGLE_CLIENT_ID !== clientIdUsedInAuthUrl) throw new Error('Client ID mismatch between auth URL and token validation'); Type guard
function isAudienceValid(idTokenBody, clientId) {
return typeof idTokenBody.aud === 'string' && idTokenBody.aud === clientId;
} Try / catch
try {
const token = await googleHelper.startOauth2(code, sub, clientId);
} catch (err) {
if (err.message === 'Client ID inconsistent.') {
// config/env mismatch: reload correct clientId and invalidate old tokens
} else throw err;
} Prevention
- Keep a single source of truth for the Google client ID used in both auth URL and validation
- Invalidate stored tokens when rotating client IDs or switching Google Cloud projects
- Separate client IDs per environment (staging/prod) and verify env vars at startup
- Log the expected vs received aud on failure to speed diagnosis
When it happens
Trigger: OAuth callback (token), signin, or refreshToken when the ID token's aud claim does not equal the configured Google client ID — e.g. clientId config changed between token issuance and validation, or the token came from a different app's client.
Common situations: Deploying with a mismatched GOOGLE_CLIENT_ID env var; rotating client IDs but keeping old refresh tokens; multiple environments (staging/prod) sharing stored tokens; copy-pasting a client ID from another Google Cloud project.
Related errors
- Google account ID not expected.
- GitLab account ID not expected.
- WordPress account ID not expected.
- Zendesk account ID not expected.
AI-assisted analysis of benweet/stackedit@6dce2a5e36 (2026-09-01).
Data as JSON: /api/errors/c9d6791a061ac63c.
Report an issue: GitHub.