Note to first-time contributors: Please open a discussion post in Discussions to discuss your idea/fix with the community before creating a pull request, and describe your changes before submitting a pull request.
Before submitting, make sure you've checked the following:
Target branch: Verify that the pull request targets the dev branch.
Description: Provided below.
Changelog: Provided below.
Documentation: No documentation changes required.
Dependencies: No new dependencies.
Testing: Manually tested - see screenshots below.
Agentic AI Code: This PR was developed with AI assistance but has undergone thorough human review and manual testing.
Code review: Self-reviewed.
Title Prefix: Using fix: prefix.
Changelog Entry
Description
MCP OAuth 2.1 tokens (e.g., Notion) expire after ~1 hour but were not being proactively refreshed. The current refresh mechanism only triggers when get_oauth_token() is called within 5 minutes of expiration. If the user isn't actively using the MCP tool during that window, the token expires, and the session is deleted on the next access attempt, requiring re-authentication.
This PR adds a background task that proactively refreshes OAuth tokens before they expire.
Added
get_expiring_sessions(minutes=10) method in OAuthSessionTable to query sessions expiring within a specified time window
periodic_oauth_token_refresh() background task that runs every 5 minutes and refreshes tokens expiring within 10 minutes
Background task startup in app lifespan with proper cleanup on shutdown
Changed
Enhanced OAuthClientManager._perform_token_refresh() to handle unregistered MCP clients by:
Looking up OAuth client info from stored tool server config (TOOL_SERVER_CONNECTIONS)
Decrypting the oauth_client_info to get client_id, client_secret, and token_endpoint
Performing the refresh even when the OAuth client isn't registered in memory (which happens after app restart)
Fixed
MCP OAuth tokens (like Notion) now automatically refresh before expiration without user intervention
Fixes the issue where users had to re-authenticate after ~1 hour of inactivity with MCP tools
INFO | open_webui.utils.oauth:periodic_oauth_token_refresh - Found 1 OAuth session(s) expiring soon, attempting refresh...
INFO | open_webui.utils.oauth:_refresh_token - Successfully refreshed token for session 9f43ad41-2a6a-4cbc-9cfa-90f228cabba9
INFO | open_webui.utils.oauth:periodic_oauth_token_refresh - Successfully refreshed MCP OAuth token for session 9f43ad41-2a6a-4cbc-9cfa-90f228cabba9 (provider: mcp:ntn)
Token expiration updated (before/after):
Before: Expires: 2025-12-08 07:42:44 (was about to expire)
After: Expires: 2025-12-08 08:23:05 (refreshed for another hour)
Contributor License Agreement
By submitting this pull request, I confirm that I have read and fully agree to the Contributor License Agreement (CLA), and I am providing my contributions under its terms.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.
## 📋 Pull Request Information
**Original PR:** https://github.com/open-webui/open-webui/pull/19811
**Author:** [@jamie-dit](https://github.com/jamie-dit)
**Created:** 12/8/2025
**Status:** ❌ Closed
**Base:** `dev` ← **Head:** `fix/mcp-oauth-proactive-refresh`
---
### 📝 Commits (1)
- [`0fe0fcf`](https://github.com/open-webui/open-webui/commit/0fe0fcff4d0644984e19a3a9bbaf84f06715e865) fix: Add proactive OAuth token refresh for MCP sessions
### 📊 Changes
**3 files changed** (+200 additions, -17 deletions)
<details>
<summary>View changed files</summary>
📝 `backend/open_webui/main.py` (+10 -0)
📝 `backend/open_webui/models/oauth_sessions.py` (+35 -0)
📝 `backend/open_webui/utils/oauth.py` (+155 -17)
</details>
### 📄 Description
# Pull Request Checklist
### Note to first-time contributors: Please open a discussion post in [Discussions](https://github.com/open-webui/open-webui/discussions) to discuss your idea/fix with the community before creating a pull request, and describe your changes before submitting a pull request.
**Before submitting, make sure you've checked the following:**
- [x] **Target branch:** Verify that the pull request targets the `dev` branch.
- [x] **Description:** Provided below.
- [x] **Changelog:** Provided below.
- [x] **Documentation:** No documentation changes required.
- [x] **Dependencies:** No new dependencies.
- [x] **Testing:** Manually tested - see screenshots below.
- [x] **Agentic AI Code:** This PR was developed with AI assistance but has undergone thorough human review and manual testing.
- [x] **Code review:** Self-reviewed.
- [x] **Title Prefix:** Using `fix:` prefix.
# Changelog Entry
### Description
MCP OAuth 2.1 tokens (e.g., Notion) expire after ~1 hour but were not being proactively refreshed. The current refresh mechanism only triggers when `get_oauth_token()` is called within 5 minutes of expiration. If the user isn't actively using the MCP tool during that window, the token expires, and the session is deleted on the next access attempt, requiring re-authentication.
This PR adds a background task that proactively refreshes OAuth tokens before they expire.
### Added
- `get_expiring_sessions(minutes=10)` method in `OAuthSessionTable` to query sessions expiring within a specified time window
- `periodic_oauth_token_refresh()` background task that runs every 5 minutes and refreshes tokens expiring within 10 minutes
- Background task startup in app lifespan with proper cleanup on shutdown
### Changed
- Enhanced `OAuthClientManager._perform_token_refresh()` to handle unregistered MCP clients by:
- Looking up OAuth client info from stored tool server config (`TOOL_SERVER_CONNECTIONS`)
- Decrypting the `oauth_client_info` to get client_id, client_secret, and token_endpoint
- Performing the refresh even when the OAuth client isn't registered in memory (which happens after app restart)
### Fixed
- MCP OAuth tokens (like Notion) now automatically refresh before expiration without user intervention
- Fixes the issue where users had to re-authenticate after ~1 hour of inactivity with MCP tools
---
### Additional Information
- Related issue: #19809
- The fix handles the case where MCP OAuth clients aren't registered in memory after app restart (they're registered lazily on first use)
- Uses the existing `oauth_client_info` stored in tool server config to discover token endpoint and credentials
### Testing Steps
1. Configure an MCP server with OAuth 2.1 (e.g., Notion)
2. Complete OAuth authorization
3. Wait for the background task to run (every 5 minutes)
4. Observe token being refreshed in logs before expiration
### Screenshots
**Background task starting:**
```
INFO | open_webui.utils.oauth:periodic_oauth_token_refresh - Starting periodic OAuth token refresh task (interval: 5 minutes)
```
**Token refresh successful:**
```
INFO | open_webui.utils.oauth:periodic_oauth_token_refresh - Found 1 OAuth session(s) expiring soon, attempting refresh...
INFO | open_webui.utils.oauth:_refresh_token - Successfully refreshed token for session 9f43ad41-2a6a-4cbc-9cfa-90f228cabba9
INFO | open_webui.utils.oauth:periodic_oauth_token_refresh - Successfully refreshed MCP OAuth token for session 9f43ad41-2a6a-4cbc-9cfa-90f228cabba9 (provider: mcp:ntn)
```
**Token expiration updated (before/after):**
- Before: `Expires: 2025-12-08 07:42:44` (was about to expire)
- After: `Expires: 2025-12-08 08:23:05` (refreshed for another hour)
### Contributor License Agreement
By submitting this pull request, I confirm that I have read and fully agree to the [Contributor License Agreement (CLA)](https://github.com/open-webui/open-webui/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT), and I am providing my contributions under its terms.
---
<sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
📋 Pull Request Information
Original PR: https://github.com/open-webui/open-webui/pull/19811
Author: @jamie-dit
Created: 12/8/2025
Status: ❌ Closed
Base:
dev← Head:fix/mcp-oauth-proactive-refresh📝 Commits (1)
0fe0fcffix: Add proactive OAuth token refresh for MCP sessions📊 Changes
3 files changed (+200 additions, -17 deletions)
View changed files
📝
backend/open_webui/main.py(+10 -0)📝
backend/open_webui/models/oauth_sessions.py(+35 -0)📝
backend/open_webui/utils/oauth.py(+155 -17)📄 Description
Pull Request Checklist
Note to first-time contributors: Please open a discussion post in Discussions to discuss your idea/fix with the community before creating a pull request, and describe your changes before submitting a pull request.
Before submitting, make sure you've checked the following:
devbranch.fix:prefix.Changelog Entry
Description
MCP OAuth 2.1 tokens (e.g., Notion) expire after ~1 hour but were not being proactively refreshed. The current refresh mechanism only triggers when
get_oauth_token()is called within 5 minutes of expiration. If the user isn't actively using the MCP tool during that window, the token expires, and the session is deleted on the next access attempt, requiring re-authentication.This PR adds a background task that proactively refreshes OAuth tokens before they expire.
Added
get_expiring_sessions(minutes=10)method inOAuthSessionTableto query sessions expiring within a specified time windowperiodic_oauth_token_refresh()background task that runs every 5 minutes and refreshes tokens expiring within 10 minutesChanged
OAuthClientManager._perform_token_refresh()to handle unregistered MCP clients by:TOOL_SERVER_CONNECTIONS)oauth_client_infoto get client_id, client_secret, and token_endpointFixed
Additional Information
oauth_client_infostored in tool server config to discover token endpoint and credentialsTesting Steps
Screenshots
Background task starting:
Token refresh successful:
Token expiration updated (before/after):
Expires: 2025-12-08 07:42:44(was about to expire)Expires: 2025-12-08 08:23:05(refreshed for another hour)Contributor License Agreement
By submitting this pull request, I confirm that I have read and fully agree to the Contributor License Agreement (CLA), and I am providing my contributions under its terms.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.