diff --git a/python/python/lancedb/remote/header.py b/python/python/lancedb/remote/header.py index 206b7a7cb..5f5bd12d8 100644 --- a/python/python/lancedb/remote/header.py +++ b/python/python/lancedb/remote/header.py @@ -141,7 +141,7 @@ class OAuthProvider(HeaderProvider): # Set expiration if provided expires_in = token_data.get("expires_in") - if expires_in: + if expires_in is not None: self._token_expires_at = time.time() + expires_in else: # Token doesn't expire or expiration unknown diff --git a/python/python/tests/test_header_provider.py b/python/python/tests/test_header_provider.py index 187b0a50a..e50ff3270 100644 --- a/python/python/tests/test_header_provider.py +++ b/python/python/tests/test_header_provider.py @@ -114,6 +114,24 @@ class TestOAuthProvider: "x-lancedb-credential-type": "oidc", } + def test_zero_lifetime_token_is_refreshed(self): + """A token that expires immediately must not be cached indefinitely.""" + call_count = 0 + + def fetcher(): + nonlocal call_count + call_count += 1 + return { + "access_token": f"token{call_count}", + "expires_in": 0, + } + + provider = OAuthProvider(fetcher, refresh_buffer_seconds=0) + + assert provider.get_headers() == {"Authorization": "Bearer token1"} + assert provider.get_headers() == {"Authorization": "Bearer token2"} + assert call_count == 2 + def test_missing_access_token(self): """Test error handling when access_token is missing."""