quarkusio/quarkus · error · OidcClientException

Only 'refresh_token' grant is supported, please call OidcCli

Error message

Only 'refresh_token' grant is supported, please call OidcClient#refreshTokens method instead

What it means

OidcClientImpl.getTokens() performs a client_credentials/password-style token grant using pre-built tokenGrantParams. If those params are null (the client was built only with a refresh grant), the only supported flow is refresh, and callers must use refreshTokens() instead — hence this OidcClientException.

Source

Thrown at extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/OidcClientImpl.java:108

        this.tokenRevokeUri = tokenRevokeUri;
        this.tokenGrantParams = tokenGrantParams;
        this.commonRefreshGrantParams = commonRefreshGrantParams;
        this.grantType = grantType;
        this.oidcConfig = oidcClientConfig;
        this.requestFilters = requestFilters;
        this.responseFilters = responseFilters;
        this.clientSecretBasicAuthScheme = clientCredentials.clientSecretBasicAuthScheme;
        this.jwtAssertionProvided = clientCredentials.jwtAssertionProvided;
        this.clientJwtKey = jwtAssertionProvided ? null : clientCredentials.clientJwtKey;
        this.clientSecret = clientCredentials.clientSecret;
        this.clientAssertionProvider = clientCredentials.clientAssertionProvider;
    }

    @Override
    public Uni<Tokens> getTokens(Map<String, String> additionalGrantParameters) {
        checkClosed();
        if (tokenGrantParams == null) {
            throw new OidcClientException(
                    "Only 'refresh_token' grant is supported, please call OidcClient#refreshTokens method instead");
        }
        return getJsonResponse(OidcEndpoint.Type.TOKEN, tokenGrantParams, additionalGrantParameters, Operation.GET);
    }

    @Override
    public Uni<Tokens> refreshTokens(String refreshToken, Map<String, String> additionalGrantParameters) {
        checkClosed();
        if (refreshToken == null) {
            throw new OidcClientException("Refresh token is null");
        }
        MultiMap refreshGrantParams = copyMultiMap(commonRefreshGrantParams);
        refreshGrantParams.add(OidcConstants.REFRESH_TOKEN_VALUE, refreshToken);
        return getJsonResponse(OidcEndpoint.Type.TOKEN, refreshGrantParams, additionalGrantParameters, Operation.REFRESH);
    }

    @Override
    public Uni<Boolean> revokeAccessToken(String accessToken, Map<String, String> additionalParameters) {

View on GitHub (pinned to e1c734241f)

Solutions

  1. Call oidcClient.refreshTokens(refreshToken, params) instead of getTokens().
  2. If getTokens() is required, configure a supported initial grant, e.g. quarkus.oidc-client.grant.type=client (client_credentials).
  3. Obtain the initial refresh token from another client/flow and only use this client for refresh operations.

Example fix

// before
Tokens t = oidcClient.getTokens().await().indefinitely();

// after
Tokens t = oidcClient.refreshTokens(refreshToken, Map.of()).await().indefinitely();
Defensive patterns

Strategy: validation

Validate before calling

if (client instanceof OidcClientImpl && isRefreshOnlyClient(config)) {
    // must use refreshTokens(), not getTokens()
}

Type guard

boolean supportsTokenGrant(OidcClientConfig cfg) {
    return !"refresh".equals(cfg.grant().type().orElse(GrantType.CLIENT).toString());
}

Try / catch

try {
    return client.getTokens(params);
} catch (OidcClientException e) {
    if (e.getMessage().contains("refresh_token")) {
        return client.refreshTokens(storedRefreshToken, params);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling oidcClient.getTokens(...) on an OidcClient configured without a grant type that produces token grant params (i.e. no client_credentials / password grant configured), so tokenGrantParams == null.

Common situations: Configuring quarkus.oidc-client.<name>.grant.type=refresh (or leaving only refresh params) and then calling getTokens() directly; calling getTokens() on a client intended solely for refreshing tokens.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/68e854d5f6652d0d. Report an issue: GitHub.