Actually, I managed to make Keycloak client do this job for me after spending some time with the issue. In my case I had to connect to a Keycloak server with password grant type, and use access token to fetch data from a third party protected endpoint in a Spring Boot server side application.
At the end I came up with a service, which provides an access token after initial authentication, and automatic refresh/re-authentication on demand.
I added a @Configuration bean, which contained the connection parameters to the third party Keycloak instance:
    package no.currentclient.application.api.config;  // real package name masked
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    @Configuration
    public class OauthClientConfig {
        public record OauthConfig(String realm, String authServerUrl, String clientId, String username, String password) {
        }
        @Bean
        OauthConfig oauthConfig(
                @Value("${client.oauth.realm}") String realm,
                @Value("${client.oauth.auth-server-url}") String authServerUrl,
                @Value("${client.oauth.resource}") String clientId,
                @Value("${client.oauth.username}") String username,
                @Value("${client.oauth.password}") String password
        ) {
            return new OauthConfig(realm,
                    authServerUrl,
                    clientId,
                    username,
                    password);
        }
    }
After I created a Spring Service which is capable of authenticating, getting and refreshing an access token:
package no.currentclient.application.auth.oauthclient;  // real package name masked
import com.fasterxml.jackson.databind.ObjectMapper;
import no.currentclient.application.api.config.OauthClientConfig;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import org.keycloak.authorization.client.representation.ServerConfiguration;
import org.keycloak.authorization.client.util.Http;
import org.keycloak.authorization.client.util.TokenCallable;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.Collections;
@Service
public class OauthTokenService {
    private final TokenCallable tokenCallable;
    public OauthTokenService(
            OauthClientConfig.OauthConfig oauthConfig,
            OkHttpClient okHttpClient
    ) throws IOException {
        var serverConfiguration = getServerConfiguration(oauthConfig.authServerUrl()+"/auth/realms/"+oauthConfig.realm()+"/.well-known/openid-configuration", okHttpClient);
        var config = new org.keycloak.authorization.client.Configuration(
                // These might all be set to null -> only tokenMinimumTimeToLive is used in TokenCallable...
                null,null,null, null,null);
        var http = new Http(config, (requestParams, requestHeaders) -> requestParams.put("client_id", Collections.singletonList("deichman")));
        tokenCallable = new TokenCallable(oauthConfig.username(), oauthConfig.password(), http, config, serverConfiguration);
    }
    /*
    * Call this method to get hold of an on-demand refreshed auth token. TokenCallable handles the burden of token
    * refresh and re-authentication in case of session timeout.
    */
    public String getAccessToken() {
        return tokenCallable.call();
    }
    private ServerConfiguration getServerConfiguration(String configUrl, OkHttpClient okHttpClient) throws IOException {
        var configRequest = new Request.Builder().url(configUrl).get().build();
        try (var response = okHttpClient.newCall(configRequest).execute()) {
            return new ObjectMapper().readValue(response.body().string(), ServerConfiguration.class);
        }
    }
}
TokenCallable hides all the complexity of refresh/re-authentication on demand.
Hope it helps a few struggling with this problem.