private OpenIdConfigurationResponse fetchOpenIdConfigurationResponse(
            final String configurationEndpoint,
            final AbstractOpenIdConfig abstractOpenIdConfig) throws IOException {

        Objects.requireNonNull(configurationEndpoint,
                "Property "
                + abstractOpenIdConfig.getFullPathStr(AbstractOpenIdConfig.PROP_NAME_CONFIGURATION_ENDPOINT)
                + " has not been set");
        LOGGER.info("Fetching open id configuration from: " + configurationEndpoint);

//        final HttpGet httpGet = new HttpGet(configurationEndpoint);
        long sleepMs = 500;
        Throwable lastThrowable = null;

        while (true) {
            try {
                final WebTarget webTarget = jerseyClientFactory.getNamedClient(JerseyClientName.OPEN_ID)
                        .target(configurationEndpoint);

                try (Response response = webTarget.request(MediaType.APPLICATION_JSON).get()) {
                    if (response.getStatus() == HttpServletResponse.SC_OK) {
                        // According to the spec, the response may contain unexpected props so as we don't easily
                        // have access to configure the client to relax jackson, do it manually.
                        // https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse
                        final String responseJson = response.readEntity(String.class);
                        LOGGER.debug("configurationEndpoint: '{}'\n{}",
                                configurationEndpoint,
                                responseJson);
                        final OpenIdConfigurationResponse openIdConfigurationResponse = parseConfigurationResponse(
                                configurationEndpoint,
                                responseJson);

                        LOGGER.info("Successfully fetched open id configuration from: " + configurationEndpoint);
                        return openIdConfigurationResponse;
                    } else {
                        throw new AuthenticationException("Received status " + response.getStatus() +
                                                          " from " + configurationEndpoint);
                    }
                }
            } catch (AuthenticationException e) {
                // This is not a connection issue so just bubble it up and likely crash the app
                // if this is happening as part of the guice injector init.
                throw e;
            } catch (Exception e) {
                // The app is pretty dead without a connection to the IDP so keep retrying
                LOGGER.warn(LogUtil.message(
                        "Unable to establish connection to the identity provider at {} to fetch Open ID " +
                        "configuration. Will try again in {}. Enable debug to see stack trace. Error: {}",
                        configurationEndpoint, Duration.ofMillis(sleepMs), e.getMessage()));

                if (LOGGER.isDebugEnabled()) {
                    if (lastThrowable == null || !e.getMessage().equals(lastThrowable.getMessage())) {
                        // Only log the stack when it changes, else it fills up the log pretty quickly
                        LOGGER.debug("Unable to establish connection to IDP at {} to fetch Open ID configuration.",
                                configurationEndpoint, e);
                    }
                    lastThrowable = e;
                }
                try {
                    Thread.sleep(sleepMs);
                } catch (final InterruptedException ie) {
                    // Nothing to do here as the
                    Thread.currentThread().interrupt();
                    throw new RuntimeException(LogUtil.message("Thread interrupted waiting to connect to {}",
                            configurationEndpoint), e);
                }

                // Gradually increase the sleep time up to a maximum
                sleepMs = (long) (sleepMs * 1.3);
                if (sleepMs >= MAX_SLEEP_TIME_MS) {
                    sleepMs = MAX_SLEEP_TIME_MS;
                }
            }
        }
    }
Combines the values from {@link AbstractOpenIdConfig} with values obtained from the external
Open ID Connect IDP server.
stroom-security/stroom-security-common-impl/src/main/java/stroom/security/common/impl/ExternalIdpConfigurationProvider.java