Re: TomEE 11 - Examples & MP JWT TCK Failures with CXF 4.2.0
Richard Zowalla <[email protected]> Thu, 19 Feb 2026 08:43:51 +0100
| Newsgroups | gmane.comp.java.openejb.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi all, After some additional feedback from our side, the issue is now resolved = in current CXF 4.2.1-SNAPSHOT. I=E2=80=99ve tested the MP JWT TCK + the other failing examples and it = looks good now. Thanks to Reta for the quick fix. Gru=C3=9F Richard > Am 17.02.2026 um 20:53 schrieb Richard Zowalla <[email protected]>: >=20 > Reta already replied on the linked PR: = https://github.com/apache/cxf/pull/2807#discussion_r2818770491 > In short: He will have a look as he did suspect issues. >=20 > Gru=C3=9F > Richard >=20 >> Am 17.02.2026 um 20:41 schrieb David Blevins = <[email protected]>: >>=20 >> Sounds good. Reta is pretty smart. >>=20 >> It's been a while since I've had my head in the CXF codebase, but if = AbstractHTTPDestination is created once per endpoint, then caching the = Principal isn't going to work. >>=20 >> It does also cache HttpServletRequest, which on its face isn't valid = unless it's a proxy that uses a thread local to resolve the actual = HttpServletRequest. I seem to recall this is the case so @Context = injection works. >>=20 >> I'm not sure that same thing is true for Principal. If Principal can = be injected via @Context and has similar thread-local-lookup. >>=20 >> If both HttpServletRequest and Principal are both simply proxies that = delegate to a thread-local, it could be fine provided the logging is = tolerant of the scenario where there is no HTTP request. >>=20 >> Course all that is just a guess -- could be off in left field. >>=20 >>=20 >> -David >>=20 >>> On Feb 17, 2026, at 11:20=E2=80=AFAM, Richard Zowalla = <[email protected]> wrote: >>>=20 >>> Thanks for your answer, David! >>>=20 >>> Actually, the commit in CXF is this one: = https://github.com/apache/cxf/pull/2807/changes#diff-eddf423fac99200bd14e1= 15467dc35809e1855cefdf3bae77f9394b8c050fc94L419 with a totally different = message "CXF-9116: Remove org.apache.cxf.feature.LoggingFeature=E2=80=9C = - don=E2=80=99t think removing logging should lead to a behavior change. = Reta from CXF did comment in his PR for the logging feature removal for = this change. The following >>>=20 >>> "some refactoring here: a number of cxf-*-security tests were = failing due to logging change: apparently when DefaultLogEventMapper is = called, the underlying HTTP request is already recycled and fails with = NPE (https://github.com/jetty/jetty.project/issues/12080 ). To mitigate = that, at least for getUserPrincipal() - capturing principal early.=E2=80=9C= >>>=20 >>> So I think the change was introduced because of test failures in = Jetty - I will leave a ping to our thread there, so we might get some = thoughts by Reta :) >>>=20 >>> Gru=C3=9F >>> Richard=20 >>>=20 >>>=20 >>>> Am 17.02.2026 um 18:52 schrieb David Blevins = <[email protected]>: >>>>=20 >>>> Thanks for all this detail. I don't recall the default in MP JWT = off the top of my head. Would need to consult the spec, possibly TCK if = the spec didn't have a clear answer. Note if the spec isn't clear, let = me know and I'll update it once we find the answer. >>>>=20 >>>> I can confirm that calling and caching getPrincipal before an HTTP = request is read is not valid for any HTTP-based security mechanism; = basic auth, digest auth, jwt, http session based, soap security, etc, = etc. It rules out everything except SSL/TLS certificate-based client = authentication, which is connection based. >>>>=20 >>>> Even if they waited till the HTTP message was read and cached for = the duration of just the request, that's still not really possible = because of these methods: >>>>=20 >>>> - HttpServletRequest.login(String username, String password); >>>> - HttpServletRequest.logout(); >>>> - HttpServletRequest.authenticate(HttpServletResponse response); >>>>=20 >>>> What they actually do, if anything at all, is completely dependent = on the underlying security framework. As is the concept of how long a = security identity lasts during a request. >>>>=20 >>>> Sounds like a situation where someone is using security framework X = which is slow, so some well-intentioned code got added that ultimately = isn't valid outside of that exact user's scenario. >>>>=20 >>>> Here's how I would approach resolving this: >>>>=20 >>>> - Find the commit that added the caching >>>> - The commit message might tell on itself (x system is slow so = let's cache) >>>> - Figure out how they imagined the caching would work: when things = are removed, added, and in what scope they imagined the cached value was = valid (request, session, connection, globally). >>>>=20 >>>> - Analyze a stack trace of the first getPrincipal that's cached. = Figure out how we possibly got there as it's not valid. Even if caching = is removed, you still can't call getPrincipal without an HTTP request, = so this has to be solved and fixed. >>>>=20 >>>>=20 >>>> -David >>>>=20 >>>>> On Feb 17, 2026, at 6:18=E2=80=AFAM, Richard Zowalla = <[email protected]> wrote: >>>>>=20 >>>>> I believe the actual issue is related to the caching mechanism in = CXF's updated code. Due to this caching, the token validation now = happens as soon as getPrincipal() is called, which occurs much earlier = in CXF 4.2.0 than in previous versions. >>>>>=20 >>>>> As a result, our current TomEE code fails because at that point in = the request lifecycle, no Authorization header may be present (e.g., for = @PermitAll endpoints), and the token validation simply fails. >>>>>=20 >>>>> Additionally, I couldn't find clear guidance in the MP JWT = specification regarding the default behavior for non-annotated JAX-RS = methods, i.e., methods without @RolesAllowed, @PermitAll, or @DenyAll. >>>>>=20 >>>>> It appears this may be vendor-specific. Should the default be: >>>>> =E2=80=A2 @PermitAll (allow unauthenticated access)? >>>>> =E2=80=A2 @DenyAll (require authentication)? >>>>> =E2=80=A2 Something else? >>>>>=20 >>>>> Gru=C3=9F >>>>> Richard >>>>>=20 >>>>>=20 >>>>>=20 >>>>>> Am 17.02.2026 um 14:54 schrieb Richard Zowalla <[email protected]>: >>>>>>=20 >>>>>> Hi all, >>>>>>=20 >>>>>> Due to a change in CXF 4.2.0 [1], specifically caching the = principal instead of looking it up on demand, we are seeing several test = failures in the MP JWT area - I am now wondering if this a thing CXF = needs to address or if we need to update our integration. For this = reason and after some debugging, I would like to get some additional = context from the past regarding the architecture of our CXF/MP JWT = integration :) >>>>>>=20 >>>>>> The failure in question can be reproduced by running = OrderTest#shouldBeRunning() from the main branch in = examples/mp-rest-jwt-principal, or by executing parts of the MP JWT TCK, = which are also failing. >>>>>>=20 >>>>>> The test calls an endpoint that, according to the test = assumptions, shouldn=E2=80=99t be protected. It passes on TomEE 10 / CXF = 4.1.5 (which does not cache the principal). The relevant code on our = side is mainly in MPJWTFilter, especially the MPJWTServletRequestWrapper = and its use of validate(=E2=80=A6). >>>>>>=20 >>>>>> Since I=E2=80=99m not an active MP JWT user, I have some (maybe = dumb?) questions: >>>>>>=20 >>>>>> According to [2], an application annotated with = @LoginConfig(authMethod =3D "MP-JWT") requires MP-JWT Access Control = (potentially for all endpoints?). >>>>>>=20 >>>>>> If that is the case, the status() method of OrderRestin = https://github.com/apache/tomee/blob/main/examples/mp-rest-jwt-principal/s= rc/main/java/org/superbiz/store/rest/OrderRest.java should require a = JWT, no? >>>>>>=20 >>>>>> However, we don=E2=80=99t add a token to the REST client in = https://github.com/apache/tomee/blob/main/examples/mp-rest-jwt-principal/s= rc/test/java/org/superbiz/store/OrderRestClient.java#L35, so the request = is sent without a bearer token and fails with a 401.=20 >>>>>>=20 >>>>>> This worked on TomEE 10 / CXF 4.1.5 and earlier. >>>>>>=20 >>>>>> I suspect some MP JWT TCK failures are caused by the same issue. = See the build here: = https://ci-builds.apache.org/job/TomEe/job/master-build-full/org.apache.to= mee$microprofile-jwt-tck/2071/ >>>>>>=20 >>>>>> Question: >>>>>>=20 >>>>>> What is the expected behavior? =46rom my reading of the spec, it = seems this endpoint shouldn=E2=80=99t be invocable without a valid = token? >>>>>>=20 >>>>>> Could anyone with more experience in this area (David, JL, = anyone?) provide some insight? >>>>>>=20 >>>>>> Thanks and Gru=C3=9F >>>>>> Richard >>>>>>=20 >>>>>> [1] = https://github.com/apache/cxf/pull/2807/changes#diff-eddf423fac99200bd14e1= 15467dc35809e1855cefdf3bae77f9394b8c050fc94L419 >>>>>> [2] = https://download.eclipse.org/microprofile/microprofile-jwt-auth-2.1/microp= rofile-jwt-auth-spec-2.1.html#_marking_a_jax_rs_application_as_requiring_m= p_jwt_access_control >>>>>>=20 >>>>>=20 >>>>=20 >>>>=20 >>>=20 >>=20 >=20