From 07e3808e2b6914860eee65d0b7effa2aa7e8c644 Mon Sep 17 00:00:00 2001 From: strawgate Date: Tue, 12 May 2026 22:39:35 -0500 Subject: [PATCH] fix: skip fallback expiry when Keycloak sends refresh_expires_in=0 The initial auth-code exchange path had a bug where val==0 kept refresh_expires_in as None, causing the fallback to be applied despite the Keycloak never-expires sentinel. Now uses the same keycloak_never_expires flag pattern as the other two code paths. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../fastmcp/server/auth/oauth_proxy/proxy.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fastmcp_slim/fastmcp/server/auth/oauth_proxy/proxy.py b/fastmcp_slim/fastmcp/server/auth/oauth_proxy/proxy.py index 864defd5f..4744249e2 100644 --- a/fastmcp_slim/fastmcp/server/auth/oauth_proxy/proxy.py +++ b/fastmcp_slim/fastmcp/server/auth/oauth_proxy/proxy.py @@ -1091,6 +1091,7 @@ class OAuthProxy(OAuthProvider, ConsentMixin): refresh_expires_in = None refresh_token_expires_at = None if idp_tokens.get("refresh_token"): + keycloak_never_expires = False if "refresh_expires_in" in idp_tokens: val = int(idp_tokens["refresh_expires_in"]) if val > 0: @@ -1101,12 +1102,11 @@ class OAuthProxy(OAuthProvider, ConsentMixin): refresh_expires_in, ) elif val == 0: - # Keycloak "never expires" sentinel - keep None - pass - else: - pass - if refresh_expires_in is None: - # Upstream didn't specify or had invalid/zero value; use fallback. + # Keycloak "never expires" sentinel — skip fallback + keycloak_never_expires = True + # else: negative/invalid — fall through to fallback + if not keycloak_never_expires and refresh_expires_in is None: + # Upstream didn't specify; use configured fallback (default 1 year). refresh_expires_in = self._fallback_refresh_token_expiry_seconds refresh_token_expires_at = time.time() + refresh_expires_in logger.debug(