gitroomhq/postiz-app · error · Error
Token request failed: ${error}
Error message
Token request failed: ${error} What it means
Apple's token endpoint (appleid.apple.com/auth/token) returned a non-2xx response while exchanging the authorization code for an id_token. The response body is embedded in the message, and Apple's body typically contains an error field such as invalid_client or invalid_grant.
Source
Thrown at apps/backend/src/services/auth/providers/apple.provider.ts:94
const { clientId } = getConfig();
const response = await fetch('https://appleid.apple.com/auth/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'authorization_code',
code,
redirect_uri: redirectUri || defaultRedirect(),
client_id: clientId,
client_secret: clientSecret(),
}).toString(),
});
if (!response.ok) {
const error = await response.text();
throw new Error(`Token request failed: ${error}`);
}
const { id_token } = await response.json();
if (!id_token) {
throw new Error('Invalid provider token');
}
return id_token;
}
async getUser(providerToken: string) {
const { clientId } = getConfig();
const decoded = decode(providerToken, { complete: true });
const { keys } = await (
await fetch('https://appleid.apple.com/auth/keys')
).json();
const key = keys.find(View on GitHub (pinned to 0f1647f749)
Solutions
- Read the appended Apple error text: invalid_client -> fix client_secret generation (key id, team id, .p8, audience https://appleid.apple.com); invalid_grant -> code expired or reused, restart the sign-in flow
- Verify APPLE_CLIENT_ID (Services ID for web) matches what's registered in the Apple developer console
- Confirm redirect_uri in the token request exactly matches the one configured on the Apple Services ID
- Generate a fresh client_secret JWT and confirm its exp is within 6 months and iat is not in the future (clock skew)
Example fix
// before
const clientSecret = jwt.sign(payload, oldKey, { header: { kid: oldKid } });
// after
const clientSecret = jwt.sign(
{ iss: process.env.APPLE_TEAM_ID, aud: 'https://appleid.apple.com', sub: clientId },
process.env.APPLE_PRIVATE_KEY,
{ algorithm: 'ES256', expiresIn: '1h', header: { kid: process.env.APPLE_KEY_ID } }
); Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
null
Try / catch
try {
const token = await appleProvider.getToken(code);
} catch (e) {
if (e instanceof Error && e.message.startsWith('Token request failed:')) {
const body = e.message.slice('Token request failed:'.length);
if (body.includes('invalid_grant')) return restartFlow(); // code expired/used
throw new ConfigurationError('Apple client credentials', body);
}
throw e;
} Prevention
- Validate APPLE_TEAM_ID/KEY_ID/PRIVATE_KEY/CLIENT_ID at boot
- Never reuse an Apple authorization code; exchange it immediately
- Regenerate the ES256 client_secret with correct kid and aud
When it happens
Trigger: POST to Apple's token endpoint with an invalid/expired authorization code, wrong client_id, malformed or expired client_secret JWT (the .p8 key secret signed with the wrong key id, team id, or audience), or a redirect_uri mismatch.
Common situations: APPLE_TEAM_ID / APPLE_KEY_ID / APPLE_PRIVATE_KEY / APPLE_CLIENT_ID env vars misconfigured; the signed client_secret JWT passed its 6-month expiry or uses a bad .p8; authorization codes reused (they're single-use, ~5 min TTL); redirect_uri not registered in Apple developer console.
Related errors
- Token request failed: ${error}
- Organization not found
- Invalid user
- Invalid provider token
- User info request failed: ${error}
AI-assisted analysis of gitroomhq/postiz-app@0f1647f749 (2026-08-27).
Data as JSON: /api/errors/406f70d46986eb02.
Report an issue: GitHub.