Skip to content

fix(admin): allow the SPNEGO pre-authentication password to be cleared - #3242

Merged
marevol merged 1 commit into
masterfrom
fix/spnego-admin-gaps
Aug 10, 2026
Merged

fix(admin): allow the SPNEGO pre-authentication password to be cleared#3242
marevol merged 1 commit into
masterfrom
fix/spnego-admin-gaps

Conversation

@marevol

@marevol marevol commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Two gaps left by #3181 / #3220 in the General settings, both on the admin write path.

1. The SPNEGO pre-authentication password cannot be cleared

updateConfig stored the password only when the submitted value survived the mask check:

if (form.spnegoPreauthPassword != null && StringUtil.isNotBlank(form.spnegoPreauthPassword.replace("*", " "))) {

That is the same shape as the other secrets on this screen, and for them it is right: the
form renders ********** instead of the stored value, so an unchanged submission must not
overwrite it. Clearing the field simply did nothing.

For SPNEGO an empty password is not "unchanged", it is a configuration:

boolean useKeyTab() {
    return this.canUseKeyTab && this.username.isEmpty() && this.password.isEmpty();
}

#3181 changed the coded defaults for spnego.preauth.username / spnego.preauth.password
to empty precisely so a keytab-based server login would work. But once any password had been
saved through this screen, the key could never be removed again, so useKeyTab() stayed
false and the keytab setup was unreachable without editing system.properties by hand.

An absent or empty submission now removes the key. A submission made only of mask characters
is still ignored, so the round trip through updateForm keeps behaving as before, and the
other secrets are untouched.

2. The NTLM prompt rule was not applied to the API

#3220 rejects spnego.allow.basic=false together with spnego.prompt.ntlm=true, because the
SPNEGO library refuses that combination when it builds its configuration — lazily, on the
first login, so without this check SSO breaks silently long after the save. The check lived
only in AdminGeneralAction#update, so PUT /api/admin/general could still store it.

Moving the same rule into the API needs one thing beyond copying it: the API merges the
request body over the stored settings, so a request that carries only one half of the pair
takes the other half from what is already stored. The check therefore runs on the merged
body, after BeanUtil.copyBeanToBean, while the request body itself is still what gets
validated against its own bean constraints. The rule is extracted to
AdminGeneralAction#isSpnegoNtlmPromptUnsupported so both paths share one definition.

Tests

AdminGeneralActionTest: 10 tests, no failures (7 + 3).

  • test_updateConfig_spnegoPreauthPassword_canBeCleared — a stored password is removed by a
    null submission (the HTML path, where LastaFlute maps an empty field to null) and by an
    empty string (the API path, which does not)
  • test_updateConfig_spnegoPreauthPassword_maskKeepsStoredValue — an updateForm /
    updateConfig round trip leaves the stored password alone
  • test_isSpnegoNtlmPromptUnsupported — the extracted rule

The first test fails against the previous code with expected: <null> but was: <secret>,
which is the defect it pins.

mvn javadoc:jar was regenerated from scratch: no new warnings from the touched files.

The General screen refused to store an empty spnego.preauth.password so
that submitting the mask rendered by updateForm would not overwrite the
stored secret. For this setting an empty value is not "unchanged" but a
configuration in its own right: the SPNEGO library only uses a keytab when
both the pre-authentication user name and the password are empty. Once any
password had been saved, a keytab setup was therefore unreachable from the
admin screen. Treat an absent or empty submission as a request to remove
the key, and keep ignoring a submission made only of mask characters.

Also apply the NTLM prompt rule to the API. The rule rejecting
spnego.allow.basic=false together with spnego.prompt.ntlm=true was only
checked on the HTML path, so the same combination could still be stored
through PUT /api/admin/general and break SSO on the next login. The API
merges the request body over the stored settings, so the check has to run
on the merged result rather than on the request body alone.
@marevol marevol self-assigned this Aug 10, 2026
@marevol marevol added this to the 15.8.0 milestone Aug 10, 2026
@marevol
marevol merged commit 8291d36 into master Aug 10, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant