fix(core): Handle invalid JSON responses from OAuth2 token endpoints (#27089)

This commit is contained in:
Andreas Fitzek
2026-03-16 16:15:06 +01:00
committed by GitHub
parent efb3f38217
commit 94f4ff8466
2 changed files with 43 additions and 1 deletions

View File

@@ -127,7 +127,17 @@ export class ClientOAuth2 {
const body = response.data as string;
if (contentType.startsWith('application/json')) {
return JSON.parse(body) as T;
try {
return JSON.parse(body) as T;
} catch {
const preview = body.length > 100 ? body.slice(0, 100) + '...' : body;
throw new ResponseError(
response.status,
body,
undefined,
`Expected JSON response from OAuth2 token endpoint but received: ${preview}`,
);
}
}
if (contentType.startsWith('application/x-www-form-urlencoded')) {

View File

@@ -139,6 +139,38 @@ describe('ClientOAuth2', () => {
expect(result.message).toEqual(`Unsupported content type: ${contentType}`);
});
it('should throw ResponseError when application/json response contains invalid JSON', async () => {
const htmlBody = '<!DOCTYPE html><html><body>Service Unavailable</body></html>';
mockTokenResponse({
status: 200,
headers: { 'Content-Type': 'application/json' },
body: htmlBody,
});
const result = await makeTokenCall().catch((err) => err);
expect(result).toBeInstanceOf(ResponseError);
expect(result.status).toBe(200);
expect(result.body).toBe(htmlBody);
expect(result.message).toContain(
'Expected JSON response from OAuth2 token endpoint but received:',
);
expect(result.message).toContain('<!DOCTYPE html>');
});
it('should truncate long invalid JSON response bodies in the error message', async () => {
const longBody = 'x'.repeat(200);
mockTokenResponse({
status: 200,
headers: { 'Content-Type': 'application/json' },
body: longBody,
});
const result = await makeTokenCall().catch((err) => err);
expect(result).toBeInstanceOf(ResponseError);
expect(result.status).toBe(200);
expect(result.message).toContain('x'.repeat(100) + '...');
});
it('should reject 4xx responses with auth errors', async () => {
mockTokenResponse({
status: 401,