Skip to content

Commit 10e1aaf

Browse files
appleboyclaude
andcommitted
fix(oauth): catch OAuthError during refresh and add async token refresh
- Include OAuthError in authenticate() exception handling so expired refresh tokens fall back to interactive flow instead of propagating - Add refresh token logic to async_authenticate() to avoid unnecessary device-flow prompts when a stored refresh token is available Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8b74376 commit 10e1aaf

1 file changed

Lines changed: 14 additions & 5 deletions

File tree

src/authgate/__init__.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from authgate.credstore import default_token_secure_store
1313
from authgate.discovery.async_client import AsyncDiscoveryClient
1414
from authgate.discovery.client import DiscoveryClient
15-
from authgate.exceptions import AuthFlowError, AuthGateError, NotFoundError
15+
from authgate.exceptions import AuthFlowError, AuthGateError, NotFoundError, OAuthError
1616
from authgate.oauth.async_client import AsyncOAuthClient
1717
from authgate.oauth.client import OAuthClient
1818
from authgate.oauth.models import Token
@@ -63,7 +63,7 @@ def authenticate(
6363
try:
6464
token = ts.token()
6565
return client, token
66-
except (NotFoundError, AuthFlowError):
66+
except (NotFoundError, AuthFlowError, OAuthError):
6767
pass
6868

6969
# 5. No valid token — run the appropriate authentication flow
@@ -111,15 +111,24 @@ async def async_authenticate(
111111
# 2. Create async OAuth client
112112
client = AsyncOAuthClient(client_id, meta.to_endpoints())
113113

114-
# 3. Check stored token
114+
# 3. Check stored token and attempt refresh if expired
115115
store = default_token_secure_store(service_name, store_path)
116116
try:
117117
stored = store.load(client_id)
118-
if stored.is_valid():
119-
from authgate.authflow.token_source import _credstore_to_oauth
118+
from authgate.authflow.token_source import _credstore_to_oauth, _oauth_to_credstore
120119

120+
if stored.is_valid():
121121
token = _credstore_to_oauth(stored)
122122
return client, token
123+
124+
# Try refreshing with the stored refresh token
125+
if stored.refresh_token:
126+
try:
127+
token = await client.refresh_token(stored.refresh_token)
128+
store.save(client_id, _oauth_to_credstore(token, client_id))
129+
return client, token
130+
except OAuthError:
131+
pass
123132
except NotFoundError:
124133
pass
125134

0 commit comments

Comments
 (0)