fix(auth): keep Pireon's OAuth error hint in token errors and logs

Passport answers token failures with a generic `invalid_request` description
and puts the actual cause in `hint` (invalid redirect URI, expired or revoked
code, code issued to another client…). The proxy dropped it, so sign-in
showed only "The request is missing a required parameter…". It is now
appended to the error message and logged with the grant type and client id.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 15:52:16 +02:00
parent cbaad17fc7
commit b1002e6599
2 changed files with 30 additions and 1 deletions

View File

@@ -184,12 +184,23 @@ export class PireonIdentityProvider extends IdentityProvider {
throw new ServiceUnavailableException('Identity server unavailable');
}
if (response.status === 400 || response.status === 401) {
// OAuth2 error (RFC 6749 §5.2). Passport puts the useful part in `hint`
// (which parameter was wrong), so keep it in the message and the log.
const error = (await response.json().catch(() => ({}))) as {
error?: string;
error_description?: string;
hint?: string;
message?: string;
};
const description =
error.error_description ?? error.message ?? 'Invalid credentials';
this.logger.warn(
`Pireon rejected ${grant.type} for client ${client.id}: ` +
`${error.error ?? response.status} — ${description}` +
(error.hint ? ` (hint: ${error.hint})` : ''),
);
throw new InvalidCredentialsError(
error.error_description ?? error.message ?? 'Invalid credentials',
error.hint ? `${description} (${error.hint})` : description,
);
}
this.assertOk(response, 'POST /oauth/token');