Skip to content

No User-Agent in HTTP requests sent by Trino to fetch Json Web Key Set (JWKS) #29669

@maxsbs

Description

@maxsbs

Trino version

481

Please describe the bug

JWK/JWKS key fetch requests do not include a User-Agent header

Summary

When Trino fetches public keys from a JWKS endpoint — for both JWT authentication (http-server.authentication.jwt.key-file) and OAuth2 authentication (http-server.authentication.oauth2.jwks-url) — the outgoing HTTP requests do not include a User-Agent header. This causes failures with reverse proxies, WAFs, or identity providers that reject requests without a User-Agent.

Affected code paths

1. JWT authentication — JwkService.java

core/trino-main/src/main/java/io/trino/server/security/jwt/JwkService.java

private Map<String, PublicKey> fetchKeys() throws RuntimeException {
    Request request = prepareGet().setUri(address).build();
    StringResponse response;
    try {
        response = httpClient.execute(request, createStringResponseHandler());
    }
    // ...
}

The HTTP client is bound in JwtAuthenticatorSupportModule.java:

httpClientBinder(binder).bindHttpClient("jwk", ForJwt.class);

2. OAuth2 authentication — NimbusAirliftHttpClient.java

core/trino-main/src/main/java/io/trino/server/security/oauth2/NimbusAirliftHttpClient.java

@Override
public Resource retrieveResource(URL url) throws IOException {
    try {
        StringResponseHandler.StringResponse response = httpClient.execute(
            prepareGet().setUri(url.toURI()).build(),
            createStringResponseHandler());
        return new Resource(response.getBody(), response.getHeader(CONTENT_TYPE).orElse(null));
    }
    // ...
}

This is used by Nimbus to fetch the JWKS endpoint during OAuth2 token validation. The HTTP client is bound in OAuth2ServiceModule.java:

httpClientBinder(binder)
    .bindHttpClient("oauth2-jwk", ForOAuth2.class)
    .withConfigDefaults(clientConfig -> clientConfig
        .setRequestBufferSize(DataSize.of(32, KILOBYTE))
        .setResponseBufferSize(DataSize.of(32, KILOBYTE)));

Root cause

Airlift's JettyHttpClient explicitly removes the default Jetty User-Agent during initialization:

airlift/http-client/src/main/java/io/airlift/http/client/jetty/JettyHttpClient.java

// remove default user agent
httpClient.setUserAgentField(null);

Since neither JwkService nor NimbusAirliftHttpClient explicitly adds a User-Agent header to their requests, and the underlying Jetty client has its default User-Agent nulled out, no User-Agent header is sent.

Impact

Any environment where the JWKS/OAuth2 endpoint is behind a reverse proxy or WAF that requires a User-Agent header (a common security policy) will fail to fetch keys, causing authentication to break entirely. This affects both JWT and OAuth2 authentication modes.

Suggested fix

Fix at the request level (minimal, targeted):

Add a User-Agent header in JwkService.fetchKeys() and NimbusAirliftHttpClient.retrieveResource():

// JwkService.java
private Map<String, PublicKey> fetchKeys() throws RuntimeException {
    Request request = prepareGet()
            .setUri(address)
            .setHeader("User-Agent", "Trino/v481")
            .build();
    // ...
}
// NimbusAirliftHttpClient.java
@Override
public Resource retrieveResource(URL url) throws IOException {
    try {
        StringResponseHandler.StringResponse response = httpClient.execute(
            prepareGet()
                .setUri(url.toURI())
                .setHeader("User-Agent", "Trino/v481")
                .build(),
            createStringResponseHandler());
        // ...
    }
}

Environment

  • Trino version: all (verified on master as of 2026-05-29)
  • Airlift version: all (the setUserAgentField(null) has been present since the Jetty migration)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions