Skip to content

Client authentication errors cannot be serialised differently without reimplementing onAuthenticationFailure #19742

Description

@nolem

This is a follow-up to #18285, where the same hook came up. There the answer was:

This is already possible. See Configuring Client Authentication and the clientAuthentication.errorResponseHandler(), which is an AuthenticationFailureHandler.

That is correct, and it is what we use. But it is the only hook, and it is all or nothing. If the thing you want to change is the serialisation of the error body, you have to take over the whole response writing.

Our case: legacy clients that expect an additional field in the error body. Nothing about status code, headers or when a failure happens, only how the OAuth2Error is written.

At the token endpoint this is a few lines, because the default failure handler is public and has a setter:

OAuth2ErrorHttpMessageConverter errorConverter = new OAuth2ErrorHttpMessageConverter();
errorConverter.setErrorParametersConverter(ourSerialisation());

OAuth2ErrorAuthenticationFailureHandler handler = new OAuth2ErrorAuthenticationFailureHandler();
handler.setErrorResponseConverter(errorConverter);
// tokenEndpoint.errorResponseHandler(handler)

ErrorSerializationTest asserts that the custom parameters really end up in the response body.

At OAuth2ClientAuthenticationFilter the same is not reachable (ClientAuthenticationFilterHooksTest):

  • the filter is final, so no subclass
  • errorHttpResponseConverter is a private final field, built in the filter itself, and there is no setter for it. The setters are setAuthenticationConverter, setAuthenticationSuccessHandler and setAuthenticationFailureHandler, nothing else
  • the filter writes the error response itself in onAuthenticationFailure

So the only way to change one field is to pass an AuthenticationFailureHandler that does again what the default does. In practice that means copying the body of onAuthenticationFailure and keeping that copy correct across upgrades, for a change that has nothing to do with failure handling.

For two filters in the same package that both write an OAuth2Error this looks like an asymmetry that was not intended, especially since the class that solves it, OAuth2ErrorAuthenticationFailureHandler, is right there.

Suggestion, either one is fine for us:

  1. add a setter for the error converter on OAuth2ClientAuthenticationFilter
  2. or give the filter the same default OAuth2ErrorAuthenticationFailureHandler that the token endpoint uses, so the existing errorResponseHandler() hook reaches the serialisation

The second is smaller and makes both endpoints behave the same way. I am happy to open a PR for the one you prefer.

Tests: https://github.com/macstab/spring-authorization-server-issues - green on 7.1.1, on 7.0.7 and on standalone 1.5.3.

Activity

  1. vanshtyagi384 commented on Sep 28, 2026

    @vanshtyagi384

    Hi maintainers,

    I'm a Java backend developer and would like to contribute to this issue.

    I understand the goal is to allow customization of client authentication error serialization without requiring a complete reimplementation of onAuthenticationFailure.

    I'm planning to trace the existing failure-handling and response-serialization flow, identify the relevant extension points, and add a regression test demonstrating the desired behavior.

    Before I begin implementing anything, could you please confirm whether this issue is available for contribution and whether there is a preferred design or approach?

    Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions