{"record":{"id":"68e854d5f6652d0d","repo":"quarkusio/quarkus","slug":"only-refresh-token-grant-is-supported-please-ca","errorCode":null,"errorMessage":"Only 'refresh_token' grant is supported, please call OidcClient#refreshTokens method instead","messagePattern":"Only 'refresh_token' grant is supported, please call OidcClient#refreshTokens method instead","errorType":"exception","errorClass":"OidcClientException","httpStatus":null,"severity":"error","filePath":"extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/OidcClientImpl.java","lineNumber":108,"sourceCode":"        this.tokenRevokeUri = tokenRevokeUri;\n        this.tokenGrantParams = tokenGrantParams;\n        this.commonRefreshGrantParams = commonRefreshGrantParams;\n        this.grantType = grantType;\n        this.oidcConfig = oidcClientConfig;\n        this.requestFilters = requestFilters;\n        this.responseFilters = responseFilters;\n        this.clientSecretBasicAuthScheme = clientCredentials.clientSecretBasicAuthScheme;\n        this.jwtAssertionProvided = clientCredentials.jwtAssertionProvided;\n        this.clientJwtKey = jwtAssertionProvided ? null : clientCredentials.clientJwtKey;\n        this.clientSecret = clientCredentials.clientSecret;\n        this.clientAssertionProvider = clientCredentials.clientAssertionProvider;\n    }\n\n    @Override\n    public Uni<Tokens> getTokens(Map<String, String> additionalGrantParameters) {\n        checkClosed();\n        if (tokenGrantParams == null) {\n            throw new OidcClientException(\n                    \"Only 'refresh_token' grant is supported, please call OidcClient#refreshTokens method instead\");\n        }\n        return getJsonResponse(OidcEndpoint.Type.TOKEN, tokenGrantParams, additionalGrantParameters, Operation.GET);\n    }\n\n    @Override\n    public Uni<Tokens> refreshTokens(String refreshToken, Map<String, String> additionalGrantParameters) {\n        checkClosed();\n        if (refreshToken == null) {\n            throw new OidcClientException(\"Refresh token is null\");\n        }\n        MultiMap refreshGrantParams = copyMultiMap(commonRefreshGrantParams);\n        refreshGrantParams.add(OidcConstants.REFRESH_TOKEN_VALUE, refreshToken);\n        return getJsonResponse(OidcEndpoint.Type.TOKEN, refreshGrantParams, additionalGrantParameters, Operation.REFRESH);\n    }\n\n    @Override\n    public Uni<Boolean> revokeAccessToken(String accessToken, Map<String, String> additionalParameters) {","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/oidc-client/runtime/src/main/java/io/quarkus/oidc/client/runtime/OidcClientImpl.java#L90-L126","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Call oidcClient.refreshTokens(refreshToken, params) instead of getTokens().","If getTokens() is required, configure a supported initial grant, e.g. quarkus.oidc-client.grant.type=client (client_credentials).","Obtain the initial refresh token from another client/flow and only use this client for refresh operations."],"exampleFix":"// before\nTokens t = oidcClient.getTokens().await().indefinitely();\n\n// after\nTokens t = oidcClient.refreshTokens(refreshToken, Map.of()).await().indefinitely();","handlingStrategy":"validation","validationCode":"if (client instanceof OidcClientImpl && isRefreshOnlyClient(config)) {\n    // must use refreshTokens(), not getTokens()\n}","typeGuard":"boolean supportsTokenGrant(OidcClientConfig cfg) {\n    return !\"refresh\".equals(cfg.grant().type().orElse(GrantType.CLIENT).toString());\n}","tryCatchPattern":"try {\n    return client.getTokens(params);\n} catch (OidcClientException e) {\n    if (e.getMessage().contains(\"refresh_token\")) {\n        return client.refreshTokens(storedRefreshToken, params);\n    }\n    throw e;\n}","preventionTips":["Match the API call to the configured grant type.","Configure grant.type=client if you need getTokens().","Centralize token acquisition in one helper that knows the client's grant."],"tags":["oidc-client","grant","api-misuse"],"backgroundTag":"wrong-grant-type","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}