private Response doJsonPost(final Invocation.Builder invocationBuilder) {
        try {
            final Builder builder = TokenRequest.builder();
            final BiConsumer<Consumer<String>, String> builderSetFunc = (func, val) -> {
                if (!NullSafe.isBlankString(val)) {
                    func.accept(val);
                }
            };
            builderSetFunc.accept(builder::clientId, getClientId());
            builderSetFunc.accept(builder::clientSecret, getClientSecret());
            builderSetFunc.accept(builder::code, code);
            builderSetFunc.accept(builder::grantType, grantType);
            builderSetFunc.accept(builder::redirectUri, redirectUri);
            builderSetFunc.accept(builder::refreshToken, refreshToken);
            builderSetFunc.accept(builder::scope, getScopesAsString());

            final TokenRequest tokenRequest = builder.build();

            final String json = objectMapper.writeValueAsString(tokenRequest);

            // json in, json out
            invocationBuilder.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_TYPE);

            LOGGER.debug("json: {}", json);
            // Do this rather than Entity.json, so we can use our own lenient object mapper
            return invocationBuilder.post(Entity.entity(json, MediaType.APPLICATION_JSON_TYPE));

        } catch (final JsonProcessingException e) {
            throw new AuthenticationException(e.getMessage(), e);
        }
    }
Allows you do define client credentials that differ from those in {@link OpenIdConfiguration}
stroom-security/stroom-security-common-impl/src/main/java/stroom/security/common/impl/OpenIdTokenRequestHelper.java