From 6a06d78309ccf049f29c5460bdcf9ce69e778c70 Mon Sep 17 00:00:00 2001 From: Alex Godbehere Date: Thu, 9 Jul 2026 12:25:59 +0100 Subject: [PATCH] Keep Keycloak SPI timeout below Keycloak's 3s hard limit Keycloak kills user-storage lookups at 3 seconds (ServicesUtils.timeBoundOne), so the SPI's 5-second request timeout could never fire. When the F+ auth service was slow the thread was interrupted mid-request and the log showed an opaque InterruptedException rather than a timeout naming the slow hop. Default the SPI timeout to 2 seconds and set the same value in the federation component service-setup provisions. --- .../FactoryPlusUserStorageProviderFactory.java | 12 ++++++++++-- acs-service-setup/lib/openid.js | 6 +++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/acs-keycloak-spi/src/main/java/uk/co/amrc/app/factoryplus/keycloak/FactoryPlusUserStorageProviderFactory.java b/acs-keycloak-spi/src/main/java/uk/co/amrc/app/factoryplus/keycloak/FactoryPlusUserStorageProviderFactory.java index bbe946e82..5ca6092d4 100644 --- a/acs-keycloak-spi/src/main/java/uk/co/amrc/app/factoryplus/keycloak/FactoryPlusUserStorageProviderFactory.java +++ b/acs-keycloak-spi/src/main/java/uk/co/amrc/app/factoryplus/keycloak/FactoryPlusUserStorageProviderFactory.java @@ -56,7 +56,12 @@ private record CachedStore(FactoryPlusUserStore store) {} static final String CONFIG_KRB_PRINCIPAL = "auth.principal"; static final String CONFIG_KRB_KEYTAB_PATH = "auth.keytab.path"; static final String CONFIG_DEFAULT_REALM = "default.realm"; - static final String DEFAULT_TIMEOUT_SECONDS = "5"; + /* Must stay below Keycloak's 3-second ServicesUtils.timeBoundOne + * hard limit on user-storage lookups. With a longer value our own + * timeout can never fire: Keycloak interrupts the thread first and + * the admin sees an opaque InterruptedException instead of a clean + * timeout naming the F+ auth service. */ + static final String DEFAULT_TIMEOUT_SECONDS = "2"; static final String DEFAULT_CACHE_TTL_SECONDS = "60"; private static final List CONFIG_PROPERTIES = @@ -73,7 +78,10 @@ private record CachedStore(FactoryPlusUserStore store) {} .property() .name(CONFIG_TIMEOUT_SECONDS) .label("Request timeout (seconds)") - .helpText("Per-request timeout for F+ auth calls.") + .helpText("Per-request timeout for F+ auth calls. Keep " + + "this below 3 seconds: Keycloak hard-kills user " + + "storage lookups at 3s, so a longer value here " + + "never takes effect.") .type(ProviderConfigProperty.STRING_TYPE) .defaultValue(DEFAULT_TIMEOUT_SECONDS) .add() diff --git a/acs-service-setup/lib/openid.js b/acs-service-setup/lib/openid.js index 178596c01..ee13fb3c0 100644 --- a/acs-service-setup/lib/openid.js +++ b/acs-service-setup/lib/openid.js @@ -183,7 +183,11 @@ class OpenIDSetup { parentId: realmUuid, config: { "auth.url": [this.auth_internal_url], - "auth.timeout.seconds": ["5"], + // Must stay below Keycloak's 3s hard limit on user + // storage lookups; a longer value never takes effect + // and slow F+ auth calls surface as an opaque + // InterruptedException instead of a clean timeout. + "auth.timeout.seconds": ["2"], "cache.ttl.seconds": ["60"], // Disable Keycloak's per-user attribute cache for this // federation. With the default (DEFAULT, cache forever)