Repository navigation
Enforce the essential acr level when the flow finishes without a step-up - #53587
Conversation
- closes: [CVE-2026-97176] Essential (forced) acr requirement silently bypassed when a browser flow re-evaluates an already active session with no interactive step #53157
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Forced ACR enforcement remains bypassable for browser flows without a conditional LoA authenticator.
Review effort: Balanced
Findings: 1
What changed in this PR
Enforces mandatory LoA checks when authentication finishes without executing a step-up condition, addressing CVE-2026-97176.
Changes:
- Registers forced-LoA validation at top-level flow completion.
- Adds protocol-specific OIDC and SAML error handling.
- Adds regression tests and upgrade documentation.
| File | Description |
|---|---|
testsuite/.../LevelOfAssuranceFlowSamlTest.java |
Adds SAML SSO regression tests. |
tests/.../LevelOfAssuranceEssentialAcrTest.java |
Adds OIDC essential-ACR coverage. |
services/.../OIDCLoginProtocol.java |
Maps LoA failures to the OIDC error. |
services/.../AuthorizationEndpointBase.java |
Handles passive LoA failures. |
services/.../DefaultAuthenticationFlow.java |
Registers final forced-LoA validation. |
services/.../AcrNotFulfilledException.java |
Introduces a dedicated exception. |
services/.../ConditionalLoaAuthenticator.java |
Uses the dedicated exception. |
docs/.../changes-27_0_0.adoc |
Documents stricter enforcement. |
core/.../OAuthErrorException.java |
Defines the new OIDC error constant. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
76427e1 to
f3c169c
Compare
f3c169c to
71a2ab1
Compare
Unreported flaky test detectedIf the flaky tests below are affected by the changes, please review and update the changes accordingly. Otherwise, a maintainer should report the flaky tests prior to merging the PR. org.keycloak.testsuite.broker.KcSamlBrokerTest#loginInResponseToEmptyKeycloak CI - FIPS IT (strict) |
There was a problem hiding this comment.
@michalvavrik Thanks, I've added inline comment in the DefaultAuthenticationFlow (related to copilot review). WDYT?
71a2ab1 to
1443540
Compare
I can't say I am sorry 😀 but @mposolda if you want to be safe, please request review on your behalf. |
There was a problem hiding this comment.
🟡 Changes recommended
Selector-assigned LoA can bypass registration/reset enforcement, and condition-free SSO mishandles essential level 0.
6 open findings
Apply selector-assigned LoA only after selected browser flow completion · New Enforce numeric ACR when no ConditionalLoaAuthenticator is configured Qualify authFlowLoa fallback for selector flows without LoA conditions · New Accept level-0 SSO sessions for flows without LoA conditions · New Account for explicit LoA on condition-free selected flows · New Document selector-assigned LoA for condition-free authentication flows · New
🧠 Review effort: Balanced
There was a problem hiding this comment.
Thanks @michalvavrik! There is conflict now. I have just the same doubt that copilot is saying, my feeling is we can always set the callback for LoA if the level is enforced. It doesn't matter the LoA condition is executed later or not (that depends on the workflow, maybe it's not done OK and, even present, it's not executed). WDYT?
For the rest I'm OK. I think that your tests cover a lot of scenarios. So I think that it's complete. Just fix the conflict in the note and this is OK to me.
There was a problem hiding this comment.
@michalvavrik Thanks! Just a quick top-of-mind review, and rather implementation-wise suggestions. I think major concerns are brought up already by @mposolda and @rmartinc.
463ec32 to
8a683f3
Compare
… step-up closes: keycloak#53157 Signed-off-by: Michal Vavřík <dev@michalvavrik.net>
8a683f3 to
a6cf386
Compare
There was a problem hiding this comment.
Thanks @michalvavrik! LGTM!
@mposolda @mabartos Please re-review when you have time. Thanks too!
There was a problem hiding this comment.
One more thing,maybe now we prefer to move the upgrading note to 26.8.x instead of 27.0.0?
There was a problem hiding this comment.
@michalvavrik @rmartinc @mabartos Thanks for the updates and review! LGTM
AFAIK on where the "Upgrading notes" are supposed to be documented. In upstream, it works like:
- In
mainbranch, it should go to the upcoming major/minor release. So right now tochanges-27_0_0.adoc. - In the respective
release*branch, it should be upcoming release. So for examplechanges-26_8_3.adocforrelease/26.8(the 26.8.2 not released yet, but that is going to be CVEB and payload for it from upstream changes like this one is already closed)
There was a problem hiding this comment.
@michalvavrik LGTM for fixing the issue, thanks! I've added a comment for a possible follow-up issue on the step-up logic.
|
Thanks everybody! |
|
@michalvavrik You can start working on the backports when you have time. |
…thout a step-up closes: keycloak#53157 backports: keycloak#53587 Signed-off-by: Michal Vavřík <dev@michalvavrik.net>
Here you go: |
…thout a step-up (#54345) closes: #53157 backports: #53587 Signed-off-by: Michal Vavřík <dev@michalvavrik.net> Signed-off-by: Martin Bartoš <mabartos@redhat.com> Signed-off-by: Ricardo Martin <rmartinc@redhat.com> Co-authored-by: Martin Bartoš <mabartos@redhat.com> Co-authored-by: Ricardo Martin <rmartinc@redhat.com>


