quarkusio/quarkus · error · OidcClientException

Refresh token is null

Error message

Refresh token is null

What it means

OidcClientImpl.refreshTokens() requires a non-null refresh token string because it is sent as the refresh_token grant parameter. A null argument fails fast with an OidcClientException rather than producing a broken token request.

Source

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

        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) {
        checkClosed();
        if (accessToken == null) {
            throw new OidcClientException("Access token is null");
        }
        OidcRequestContextProperties requestProps = getRequestProps(null);

        if (tokenRevokeUri != null) {
            MultiMap tokenRevokeParams = MultiMap.caseInsensitiveMultiMap();
            tokenRevokeParams.set(OidcConstants.REVOCATION_TOKEN, accessToken);
            return withAsyncCredentials().flatMap(asyncCredentials -> postRequest(requestProps,

View on GitHub (pinned to e1c734241f)

Solutions

  1. Check the refresh token for null/blank before calling refreshTokens() and re-authenticate (or call getTokens()) if absent.
  2. Persist Tokens.refreshToken only when present and handle the absent case in your token store.
  3. Verify the OIDC provider actually issues refresh tokens (offline_access scope or equivalent) for the configured grant.

Example fix

// before
Tokens t = oidcClient.refreshTokens(current.getRefreshToken(), Map.of()).await().indefinitely();

// after
if (current.getRefreshToken() != null) {
    Tokens t = oidcClient.refreshTokens(current.getRefreshToken(), Map.of()).await().indefinitely();
} else {
    Tokens t = oidcClient.getTokens().await().indefinitely();
}
Defensive patterns

Strategy: type-guard

Validate before calling

String rt = tokens.getRefreshToken();
if (rt == null || rt.isBlank()) {
    throw new IllegalStateException("No refresh token available; re-authentication required");
}

Type guard

boolean hasRefreshToken(Tokens t) { return t != null && t.getRefreshToken() != null && !t.getRefreshToken().isBlank(); }

Try / catch

try {
    return client.refreshTokens(rt, params);
} catch (OidcClientException e) {
    if (e.getMessage().contains("Refresh token is null")) {
        return reauthenticate();
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling oidcClient.refreshTokens(null, additionalGrantParameters) — typically when the stored/previous Tokens had no refresh token (e.g. the OP did not issue one) and null was propagated.

Common situations: Identity providers that omit refresh_token in responses; persisting Tokens without checking refresh token availability; code assuming a refresh token always exists.

Related errors


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