spring-projects/spring-security · error · IllegalArgumentException

targetUri cannot contain query or fragment parts

Error message

targetUri cannot contain query or fragment parts

What it means

DPoPProofContext.validate rejects target URIs that contain a query string or fragment. Per RFC 9449, the DPoP proof htu claim must be the target URI without query or fragment components, so a URI with either is considered invalid input. This is thrown as an IllegalArgumentException after the URI passed URL parsing.

Source

Thrown at oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/DPoPProofContext.java:178

			return new DPoPProofContext(this.dPoPProof, this.method, this.targetUri, this.accessToken);
		}

		private void validate() {
			if (!"GET".equals(this.method) && !"HEAD".equals(this.method) && !"POST".equals(this.method)
					&& !"PUT".equals(this.method) && !"PATCH".equals(this.method) && !"DELETE".equals(this.method)
					&& !"OPTIONS".equals(this.method) && !"TRACE".equals(this.method)) {
				throw new IllegalArgumentException("method is invalid");
			}
			URI uri;
			try {
				uri = new URI(this.targetUri);
				uri.toURL();
			}
			catch (Exception ex) {
				throw new IllegalArgumentException("targetUri must be a valid URL", ex);
			}
			if (uri.getQuery() != null || uri.getFragment() != null) {
				throw new IllegalArgumentException("targetUri cannot contain query or fragment parts");
			}
		}

	}

}

View on GitHub (pinned to 96852e8860)

Solutions

  1. Strip the query and fragment before building the proof: use uriComponentsBuilder.replaceQuery(null).fragment(null).build().toUriString().
  2. Pass only the endpoint base URL for the token/resource request.
  3. If you need the request URL, reconstruct htu from scheme, host, port, and path only.
  4. Validate with uri.getQuery() == null && uri.getFragment() == null before calling the proof builder.

Example fix

// before
new DPoPProofContext("POST", "https://server/oauth2/token?grant_type=x", ...); // throws
// after
new DPoPProofContext("POST", "https://server/oauth2/token", ...);
Defensive patterns

Strategy: validation

Validate before calling

URI uri = URI.create(targetUri);
if (uri.getQuery() != null || uri.getFragment() != null) {
    throw new IllegalArgumentException("targetUri must not contain query or fragment");
}

Type guard

boolean isBareEndpointUrl(String s) {
    URI u = URI.create(s);
    return u.getQuery() == null && u.getFragment() == null;
}

Prevention

When it happens

Trigger: Constructing a DPoPProofContext with a targetUri like "https://server/oauth2/token?grant_type=client_credentials" or "https://server/oauth2/token#frag".

Common situations: Passing the full request URL (which includes query params) instead of the bare endpoint URL, or appending OAuth parameters to the token endpoint URL when they belong in the POST body.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/9ecc30f59a1a30c8. Report an issue: GitHub.