Petr Kadlec created CXF-7931:
--------------------------------
Summary: WebTarget re-encodes query in URI
Key: CXF-7931
URL: https://issues.apache.org/jira/browse/CXF-7931
Project: CXF
Issue Type: Bug
Components: JAX-RS
Affects Versions: 3.1.8
Environment: Tested on Windows in TomEE-plus 7.0.2, which contains,
IIANM, CXF 3.1.8.
Reporter: Petr Kadlec
Creating a WebTarget with a given URI instance (or anything else, see below)
does not make the request use the given URI; before the real request is made,
the query part of the URI (and possibly other parts) is re-encoded. For a
specific example, colons in the query are replaced with their URI-encoded
version, %3A (even though it is unnecessary, colons belong to the pchar class
allowed in the query component, see 3.4 and 3.3 of RFC 3986; however, the point
is not that the re-encoding is "too strict", the point is that the re-encoding
takes place at all).
While it may look harmlessly at a first glance (%3A and : are just two variants
how to encode the same text), it is in fact not harmless at all. Specifically,
SAML2 requests using the HTTP-redirect binding are sensitive to the exact text
of the request URI because of the request signatures. See the explicit remark
in [SAMLBindings] 3.4.4.1:
{quote}Further, note that URL-encoding is not canonical; that is, there are
multiple legal encodings for a given value. The relying party MUST therefore
perform the verification step using the original URL-encoded values it received
on the query string. It is not sufficient to re-encode the parameters after
they have been processed by software because the resulting encoding may not
match the signer's encoding.
{quote}
So if a SAML2 request is passed or proxied using CXF, it gets broken if it
contains anything encoded in a different way than CXF's UriBuilderImpl choose
to encode it.
Moreover, AFAICT, there is no way to override this behavior. Even implementing
our own UriBuilder which strives to keep the URI intact, and passing it to the
.target(UriBuilder) overload, it's contents is retrieved via getCurrentURI(),
the resulting (still-correct) URI is then (in resetCurrentUri()) passed to a
new explicitly-constructed UriBuilderImpl, parsing to be re-encoded later.
Reproducible example:
{{ClientBuilder.newBuilder()}}
{{ .build()}}
{{ .target(new URI("http://localhost:5544/x?q=1:2"))}}
{{ .request(MediaType.APPLICATION_JSON)}}
{{ .get();}}
Expected: a HTTP request is made to {{/x?q=1:2}}.
Actual: a HTTP request is made to {{/x%3Aq=1:2}}.
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)