Skip to content

IBX-11973: Kept blank login fields distinguishable on authentication failure - #143

Open
tischsoic wants to merge 2 commits into
6.0from
IBX-11973-blank-credential-fields
Open

IBX-11973: Kept blank login fields distinguishable on authentication failure#143
tischsoic wants to merge 2 commits into
6.0from
IBX-11973-blank-credential-fields

Conversation

@tischsoic

@tischsoic tischsoic commented Sep 8, 2026

Copy link
Copy Markdown
Contributor
🎫 Issue IBX-11973

Related PRs:

Description:

Because admin-ui never gets told which field was blank — ibexa/user throws that information away before the template runs.

DefaultAuthenticationFailureHandler replaces every BadCredentialsException with one carrying a flat "Bad credentials.", so an unknown user cannot be told apart from a wrong password. That also hides which submitted field was left empty, which the login screen needs in order to mark that field invalid instead of showing a banner.

Blank fields are now carried on a BlankCredentialsException (a BadCredentialsException subclass) with the same message and code as before — only the extra data is new, so anything that renders error.message is unaffected. Enumeration protection is untouched: the flattening of UserNotFoundException / AccountStatusException still happens, and knowing that the field you submitted was empty says nothing about whether an account exists.

Which fields are blank is read from the request rather than from the authenticator's exception message, for two reasons: the message is a sprintf over the configurable username_parameter, and FormLoginAuthenticator throws on the username first, so it can never report both fields at once. Reading the request reports both.

The exception is stored in the session, and AuthenticationException::__serialize() only carries token/code/message/file/line — hence the __serialize()/__unserialize() overrides, without which the field list is silently lost on the redirect.

For QA:

Back office /admin/login (needs ibexa/admin-ui#2058 for the visible part):

  1. Submit with both fields empty — both are marked invalid, one message each, no banner.
  2. Submit with only one field filled — only the empty one is marked.
  3. Submit a wrong password — unchanged: "Bad credentials." banner, neither field marked.
  4. Sign in normally — unchanged.

Without ibexa/admin-ui#2058 nothing changes visibly anywhere, including the storefront and customer portal login screens, which render the message only.

Documentation:

…failure

The failure handler flattens every BadCredentialsException to a single
"Bad credentials." message so that an unknown user cannot be told apart
from a wrong password. That also hid which submitted field was left
empty, which the login screen needs to mark the field invalid.

Blank fields are read from the submitted request rather than from the
authenticator's message, so both can be reported at once — Symfony stops
at the username. The message and the flattening of everything else are
unchanged, so templates that only render the message are unaffected.

Co-Authored-By: Claude <noreply@anthropic.com>

@konradoboza konradoboza left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While the change itself looks kinda ok we miss the test coverage within DefaultAuthenticationFailureHandlerTest. Feel free to use https://github.com/ibexa/internal-ai/pull/3 if needed.

Adds the cases the failure handler now distinguishes: each field blank on
its own, both at once, and the asymmetry it inherits from the
authenticator — a whitespace-only login counts as blank, a whitespace-only
password does not.

The existing message test now posts filled credentials, so it keeps
covering the plain path rather than silently taking the new one.

Co-Authored-By: Claude <noreply@anthropic.com>
@sonarqubecloud

sonarqubecloud Bot commented Sep 8, 2026

Copy link
Copy Markdown

* @param list<self::FIELD_*> $blankFields
*/
public function __construct(
array $blankFields,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To simplify it, that could be public readonly constructor promoted property (to reduce code and get rid of its getter).

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants