Skip to content

THREESCALE-8006 fix(oidc): set request timeout for OIDC query - #1601

Open
tkan145 wants to merge 2 commits into
3scale:masterfrom
tkan145:THREESCALE-8006
Open

THREESCALE-8006 fix(oidc): set request timeout for OIDC query#1601
tkan145 wants to merge 2 commits into
3scale:masterfrom
tkan145:THREESCALE-8006

Conversation

@tkan145

@tkan145 tkan145 commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

What

Fix https://redhat.atlassian.net/browse/THREESCALE-8006

Verification steps

  • Checkout this branch
  • Build new runtime image
make runtime-image IMAGE_NAME=apicast-test 
  • Get inside dev-env
cd dev-environments/keycloak-env/
  • Modify docker-compose.yml as follow
diff --git a/dev-environments/keycloak-env/docker-compose.yml b/dev-environments/keycloak-env/docker-compose.yml
index 3af7e33f..7083fc81 100644
--- a/dev-environments/keycloak-env/docker-compose.yml
+++ b/dev-environments/keycloak-env/docker-compose.yml
@@ -9,13 +9,15 @@ services:
     - example.com
     - two.upstream
     - keycloak
+    - keycloak.upstream
     environment:
       THREESCALE_CONFIG_FILE: /tmp/config.json
       THREESCALE_DEPLOYMENT_ENV: staging
-      APICAST_CONFIGURATION_LOADER: lazy
+      APICAST_CONFIGURATION_LOADER: boot
       APICAST_WORKERS: 1
       APICAST_LOG_LEVEL: debug
-      APICAST_CONFIGURATION_CACHE: "0"
+      APICAST_CONFIGURATION_CACHE: "300"
     expose:
       - "8080"
       - "8090"
@@ -36,8 +38,19 @@ services:
     expose:
       - "8080"
   keycloak:
-    image: quay.io/keycloak/keycloak:23.0.4
+    image: quay.io/openshift-logging/alpine-socat:1.8.0.0
     container_name: keycloak
+    command:
+      - "-d"
+      - "-v"
+      - "-d"
+      - "TCP-LISTEN:8080,reuseaddr,fork"
+      - 'SYSTEM:sleep 30 && exec socat - TCP\:keycloak.upstream\:8080'
+    expose:
+      - "8080"
+    restart: unless-stopped
+  keycloak.upstream:
+    image: quay.io/keycloak/keycloak:23.0.4
     command: "start-dev"
     expose:
       - "8080"
  • Start the gateway
make gateway IMAGE_NAME=apicast-test

You should see the gateway hang for 5s then start as normal

  • Stop the gateway
CTRL-L
  • Add APICAST_OIDC_CONNECT_TIMEOUT: "20" to docker-compose file
  • Start the gateway again, this time it should wait for 20s

@tkan145
tkan145 requested a review from a team as a code owner August 26, 2026 21:42
@tkan145
tkan145 requested a review from a team as a code owner August 27, 2026 07:17
@tkan145 tkan145 changed the title THREESCALE-8006 feat(oidc): set request timeout for OIDC query THREESCALE-8006 fix(oidc): set request timeout for OIDC query Aug 27, 2026
Set the connection timeout to 5s to prevent request hanging
idenfinetely when an OIDC issuer is unreachable or slow to respond.

@borisurbanik borisurbanik left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is one gotcha here that needs a fix. Because remote_v2 is loading oidc on its own, the oidc loader is only used when local-file configuration is provided. The remote_v2 loader bypasses resty/oidc/discovery.new (see the custom client here

local http_client = http_ng.new{
backend = opts.client,
options = {
headers = { ['User-Agent'] = user_agent() },
ssl = { verify = resty_env.enabled('OPENSSL_VERIFY') }
}
}
).

if err then
ngx.log(ngx.ERR, 'OIDC discovery failed for service ', service.id,
' (issuer: ', service.proxy.oidc_issuer_endpoint or 'nil', '): ',
result)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the error log message - the discovery method returns nil on error, I think you meant to log err here instead of result

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


-- First service should have error
assert.equals(21, decoded.oidc[1].service_id)
-- assert.is_not_nil(decoded.oidc[1].error)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no functionality implemented to leave or check that there was a timeout error during configuration loading. Once it times out here that service will simply fail on JWT verification later.

I'm assuming that's intentional? Or should we make sure there will be some lazy loading for the failing services later? The JIRA was open to address an oidc service that never loads so it's probably intentional, just wanted to confirm.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's designed this way; there's no need to retry the OIDC configuration on every request, which would only add unnecessary latency. APIcast will reload the configuration every 5 minutes or so, and then reload the entire OIDC anyway.

@tkan145

tkan145 commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

There is one gotcha here that needs a fix. Because remote_v2 is loading oidc on its own, the oidc loader is only used when local-file configuration is provided. The remote_v2 loader bypasses resty/oidc/discovery.new (see the custom client here

Good catch, fixed. Thanks

@tkan145
tkan145 requested a review from borisurbanik September 2, 2026 04:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants