apache/pulsar · critical · PulsarClientException.AuthenticationException

Unable to retrieve OAuth 2.0 server metadata

Error message

Unable to retrieve OAuth 2.0 server metadata

What it means

FlowBase.initialize() resolves the OAuth2 server metadata (well-known configuration) from the issuerUrl. If the resolver throws IOException, it logs the error and throws AuthenticationException('Unable to retrieve OAuth 2.0 server metadata'). The client could not fetch/discover endpoints like the token endpoint from the IdP.

Source

Thrown at pulsar-client/src/main/java/org/apache/pulsar/client/impl/auth/oauth2/FlowBase.java:251

        Duration duration;
        if (value == null) {
            log.debug().attr("name", name)
                    .attr("defaultValue", defaultValue)
                    .log("Configuration is using the default value");
            duration = defaultValue;
        } else {
            log.debug().attr("name", name).attr("value", value).log("Configuration");
            duration = value;
        }
        return duration;
    }

    public void initialize() throws PulsarClientException {
        try {
            this.metadata = createMetadataResolver().resolve();
        } catch (IOException e) {
            log.error().exception(e).log("Unable to retrieve OAuth 2.0 server metadata");
            throw new PulsarClientException.AuthenticationException("Unable to retrieve OAuth 2.0 server metadata");
        }
    }

    protected MetadataResolver createMetadataResolver() {
        return DefaultMetadataResolver.fromIssuerUrl(issuerUrl, getHttpClient(), wellKnownMetadataPath);
    }

    static String parseParameterString(Map<String, String> params, String name) {
        String s = params.get(name);
        if (StringUtils.isEmpty(s)) {
            throw new IllegalArgumentException("Required configuration parameter: " + name);
        }
        return s;
    }

    static URL parseParameterUrl(Map<String, String> params, String name) {
        String s = params.get(name);
        if (StringUtils.isEmpty(s)) {

View on GitHub (pinned to 820761864e)

Solutions

  1. Verify issuerUrl is correct and reachable (curl the well-known metadata URL from the client host)
  2. Fix TLS trust (import the IdP certificate into the truststore) if certificate errors occur
  3. Check proxy/firewall rules allowing HTTPS to the issuer host

Example fix

// before
authParams.put("issuerUrl", "https://auth.example.com/realms/tenant"); // wrong realm
// after
authParams.put("issuerUrl", "https://auth.example.com/realms/correct-tenant");
Defensive patterns

Strategy: retry

Validate before calling

String wellKnown = issuerUrl.replaceAll("/$", "") + "/.well-known/openid-configuration";
HttpURLConnection c = (HttpURLConnection) new java.net.URI(wellKnown).toURL().openConnection();
c.setConnectTimeout(5000);
if (c.getResponseCode() != 200) {
    throw new IllegalStateException("IdP metadata not reachable at " + wellKnown + ": HTTP " + c.getResponseCode());
}

Try / catch

try {
    flow.initialize();
} catch (PulsarClientException.AuthenticationException e) {
    if (e.getMessage().equals("Unable to retrieve OAuth 2.0 server metadata")) {
        // transient outage: retry with backoff; persistent: check issuerUrl/TLS/proxy
        retryWithBackoff(() -> flow.initialize());
    } else throw e;
}

Prevention

When it happens

Trigger: issuerUrl host unreachable or DNS failure; well-known metadata path (e.g. /.well-known/openid-configuration) returns 404; TLS certificate issues; start() called with no network access.

Common situations: Air-gapped or firewalled environments blocking the client from the IdP; wrong issuerUrl (trailing path mistakes, http vs https); self-signed certs not in the truststore; IdP that does not publish standard well-known metadata.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/fd7002dbce98ccb5. Report an issue: GitHub.