Uploaded image for project: 'CXF'
  1. CXF
  2. CXF-7931

WebTarget re-encodes query in URI

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • 3.1.8
    • None
    • JAX-RS
    • None
    • Tested on Windows in TomEE-plus 7.0.2, which contains, IIANM, CXF 3.1.8.

    • Unknown

    Description

      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:

      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.

      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, its 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?q=1%3A2.

      Attachments

        Activity

          People

            Unassigned Unassigned
            mormegil Petr Kadlec
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated: