feat: auto-refresh expired OAuth tokens before prompting for re-auth#50
feat: auto-refresh expired OAuth tokens before prompting for re-auth#50tomaszkoperski-bot-lars wants to merge 2 commits intosteipete:mainfrom
Conversation
When an OAuth access token expires, mcporter now automatically attempts to refresh it using the stored refresh_token before falling back to the full browser-based OAuth flow. Changes: - Add 'expired' token detection to error-classifier.ts - Add oauth-refresh.ts with tryRefreshTokens() helper - Update runtime/transport.ts to try token refresh on auth errors This improves UX for servers like Homey that return 'token expired' errors, avoiding the need for manual re-authentication when a valid refresh token is available.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f73343295b
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
src/runtime/transport.ts
Outdated
| // Try to refresh the token before falling back to full OAuth flow | ||
| if (activeDefinition.auth === 'oauth') { | ||
| logger.info(`Token expired for '${activeDefinition.name}', attempting refresh...`); | ||
| const refreshedToken = await tryRefreshTokens(activeDefinition, logger); |
There was a problem hiding this comment.
Attempt refresh before OAuth browser flow is started
Because the OAuth session is created and passed into connectWithAuth before this refresh block runs, an expired token will already trigger the OAuth browser flow (see connectWithAuth waiting for browser approval in src/runtime/oauth.ts) and may block for the timeout before this refresh is attempted. That means users still see the re-auth prompt even when a refresh token exists, which contradicts the intended “refresh before prompting” behavior and adds a 60s delay in the common expired‑token case. Consider trying tryRefreshTokens before creating the OAuth session / calling connectWithAuth, or incorporating refresh into connectWithAuth before it waits for the authorization code.
Useful? React with 👍 / 👎.
Address Codex review feedback: the refresh logic was unreachable because connectWithAuth() catches 401 errors internally when an OAuth session exists, waiting for browser approval before the outer catch block runs. The fix: 1. First try connecting WITHOUT an OAuth session (maxAttempts=0) 2. If we get a 401, attempt token refresh immediately 3. If refresh succeeds, retry with the new token 4. Only if refresh fails, create the OAuth session for browser flow This ensures users aren't prompted for browser re-auth when a simple token refresh would suffice, avoiding the 60s timeout delay.
|
Thanks for the feedback @chatgpt-codex-connector! You were right - the refresh logic was unreachable because The fix (ab78f95):
This ensures the intended behavior: users aren't prompted for browser re-auth when a simple token refresh would suffice. |
|
To use Codex here, create a Codex account and connect to github. |
Problem
When an OAuth access token expires, mcporter currently prompts for a full browser-based re-authentication flow, even when a valid refresh_token is available. This is particularly noticeable with services like Homey (mcp.athom.com) that return errors like:
Solution
This PR adds automatic token refresh before falling back to the OAuth browser flow:
Error detection: Added "expired" token pattern to
error-classifier.tsso messages like "token expired" are correctly identified as auth errors.Token refresh helper: New
oauth-refresh.tsmodule withtryRefreshTokens()that:api.athom.com/oauth2/token)Transport integration: Modified
runtime/transport.tsto try token refresh when encountering an auth error, before falling back to the full OAuth flow.Testing
Tested with Homey MCP server where tokens expire after 1 hour:
Notes