-
Notifications
You must be signed in to change notification settings - Fork 1.4k
feat: add OpenAI Codex OAuth PKCE install flow #1129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
@Wendong-Fan @Pakchoioioi would you review my PR? |
|
Also, @Wendong-Fan would you check my DM on discord? |
6c8f1c0 to
30877f8
Compare
|
Why these are cancelled? |
|
Hi @eureka928! Thanks for your contribution! I'm doing a detailed review, @Pakchoioioi Could you help review the OAuth flow? |
30877f8 to
e64c519
Compare
|
Fixed the testing |
f33d37b to
bdbc3e3
Compare
|
Follow up on this |
bytecii
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Left some comments
- Extract Codex config constants (CODEX_CONFIG_GROUP, CODEX_CONFIG_NAME, CODEX_POLL_TIMEOUT_MS) in ToolSelect.tsx - Extract CODEX_TOKEN_PATH constant and clarify CODEX_CLIENT_ID is a fixed public value in codex_toolkit.py - Simplify expires_in/expires_at: compute absolute expiry from relative value and only persist expires_at - Add FileLock around token file reads/writes to prevent parallel update races - Add TODO for response status string improvement and refactor of shared OAuth install logic - Apply formatting suggestion on codex uninstall message
|
Hi @bytecii addressed all comments |
|
I updated all, please review again |
- Extract Codex config constants (CODEX_CONFIG_GROUP, CODEX_CONFIG_NAME, CODEX_POLL_TIMEOUT_MS) in ToolSelect.tsx - Extract CODEX_TOKEN_PATH constant and clarify CODEX_CLIENT_ID is a fixed public value in codex_toolkit.py - Simplify expires_in/expires_at: compute absolute expiry from relative value and only persist expires_at - Add FileLock around token file reads/writes to prevent parallel update races - Add TODO for response status string improvement and refactor of shared OAuth install logic - Apply formatting suggestion on codex uninstall message
5326462 to
bdaec62
Compare
- Extract Codex config constants (CODEX_CONFIG_GROUP, CODEX_CONFIG_NAME, CODEX_POLL_TIMEOUT_MS) in ToolSelect.tsx - Extract CODEX_TOKEN_PATH constant and clarify CODEX_CLIENT_ID is a fixed public value in codex_toolkit.py - Simplify expires_in/expires_at: compute absolute expiry from relative value and only persist expires_at - Add FileLock around token file reads/writes to prevent parallel update races - Add TODO for response status string improvement and refactor of shared OAuth install logic - Apply formatting suggestion on codex uninstall message
bdaec62 to
89cf2bc
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks @eureka928 for contribution!
|
@Wendong-Fan please review again, I addressed all comments |
Wendong-Fan
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
Good catch — moved |
Wendong-Fan
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks @eureka928 's update,
as discussed Codex should not be treated as a "tool" in tool_controller.py. Looking at the implementation:
# codex_oauth.py
if token_data.get("access_token"):
os.environ["OPENAI_API_KEY"] = token_data["access_token"]
The OAuth flow simply obtains an OPENAI_API_KEY, Codex is fundamentally an authentication method for the OpenAI provider, not a standalone tool like Notion or Google Calendar.
now Codex endpoints (/install/tool/codex, /uninstall/tool/codex, /codex/status, /codex/save-token) are in tool_controller.py alongside actual MCP tools which is not in the right place
in /tools/available response: Codex is listed as an available "tool"
Suggested Refactor:
Move Codex OAuth logic to a provider/model authentication controller (or create one), since it belongs with OpenAI provider configuration, which the frontend already handles correctly in Models.tsx
Implements Authorization Code + PKCE flow using Codex CLI's public client_id. Handles background OAuth via localhost callback server, token persistence at ~/.eigent/tokens/codex/, and refresh logic.
Add codex handling to install_tool and uninstall_tool endpoints. Add POST /codex/save-token for manual API key fallback and GET /codex/status for token status. Add Codex to available tools list.
Add CODEX enum to ConfigGroup and corresponding entry in ConfigInfo.configs with OPENAI_API_KEY env var and codex_oauth toolkit.
Add Codex config check in useIntegrationManagement for installed state and uninstall cleanup. Add Codex case in IntegrationList handleInstall to trigger onInstall directly without env dialog.
Add Codex onInstall handler with OAuth status polling in MCP.tsx settings page and ToolSelect.tsx AddWorker flow, following the existing Google Calendar authorization pattern.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: bytecii <994513625@qq.com>
- Extract Codex config constants (CODEX_CONFIG_GROUP, CODEX_CONFIG_NAME, CODEX_POLL_TIMEOUT_MS) in ToolSelect.tsx - Extract CODEX_TOKEN_PATH constant and clarify CODEX_CLIENT_ID is a fixed public value in codex_toolkit.py - Simplify expires_in/expires_at: compute absolute expiry from relative value and only persist expires_at - Add FileLock around token file reads/writes to prevent parallel update races - Add TODO for response status string improvement and refactor of shared OAuth install logic - Apply formatting suggestion on codex uninstall message
- Add Fernet encryption for token storage using cryptography library - Derive encryption key from machine-specific identifiers (username, hostname, machine-id) using PBKDF2HMAC with 100k iterations - Set restrictive file permissions (0600) on encrypted token file - Tokens tied to specific machine for additional security
…t config Address review feedback: Codex OAuth obtains an OpenAI API key for model access, not agent tools. After successful OAuth, the key is now saved via the Provider API (/api/provider) so it integrates with the model provider configuration system. Changes: - Backend: return access_token in Codex install response for provider storage - Frontend: replace /api/configs storage with /api/provider for Codex - Server: mark CODEX ConfigInfo entry as type=provider with empty env_vars - i18n: add missing codex translation keys, remove verbose t() fallback pattern - Fix stray merge conflict marker in ToolSelect.tsx - Remove debug console.log statements from MCP.tsx
- Save CODEX_OAUTH_TOKEN marker config after OAuth to track install state - Check marker config instead of OPENAI_API_KEY for install detection - Avoid mutating input dict in CodexOAuthManager.save_token() - Add CODEX_OAUTH_TOKEN to Codex env_vars whitelist in server config - Prioritize named integration descriptions over env_vars fallback
Codex OAuth is a model-provider integration, not a toolkit. Remove it from ConfigInfo.configs so it no longer appears in the /api/config/info response that drives the MCP & Tools UI. Also remove Codex-specific install detection and uninstall handling from useIntegrationManagement and IntegrationList.
Remove the entire Codex onInstall handler, saveCodexAsProvider, and saveCodexMarkerConfig helpers from MCP.tsx and ToolSelect.tsx. Extract OAuth polling constants (OAUTH_POLL_INTERVAL_MS, OAUTH_POLL_TIMEOUT_MS) to replace inline magic numbers in the remaining Google Calendar flow. Add TODO for status string enum extraction.
Add a "Connect via Codex" button to the OpenAI BYOK provider panel in the Models settings page. The OAuth PKCE flow obtains an OpenAI API key and saves it as a provider, with a marker config for state detection. - Add handleCodexOAuth, saveCodexAsProvider, handleCodexDisconnect - Extract refreshProviderForm helper to deduplicate provider list sync - Show "or" divider between Codex OAuth and manual API key entry - Disconnect properly revokes token, removes marker, and resets provider - Add i18n keys for connect/disconnect/status UI text
Codex OAuth is a provider credential manager, not an agent toolkit. Move it to app/utils/codex_oauth.py alongside oauth_state_manager.py.
95d92c8 to
d09ccba
Compare
…ntroller Codex OAuth is an authentication method for the OpenAI provider, not a standalone MCP tool. Move all Codex endpoints to a dedicated controller with semantically correct paths (/codex/connect, /codex/disconnect) and update the frontend to use the new routes.

Description
This PR adds support for installing and authenticating OpenAI Codex as a tool via OAuth PKCE flow. Users can install Codex from both the Settings/MCP page and the AddWorker tool selection, with automatic token management including refresh and expiry handling.
Closes #834
Key Changes:
Backend (
backend/):app/utils/toolkit/codex_toolkit.py— NewCodexOAuthManagerimplementing the full OpenAI OAuth PKCE flow (authorization URL generation, token exchange, refresh, revocation, and persistent token storage via keyring)app/controller/tool_controller.py— New endpoints for Codex install, uninstall, save-token, and status; integrated into existing/install/{tool}and/uninstall/{tool}routesServer (
server/):app/model/config/config.py— AddedCODEXconfig group withOPENAI_API_KEYenvironment variable mappingapp/type/config_group.py— RegisteredcodexinConfigGroupenum andCONFIG_GROUP_ENV_VARSFrontend (
src/):src/pages/Setting/MCP.tsx— Codex card in Settings with install/uninstall buttons and OAuth callback handlingsrc/components/AddWorker/ToolSelect.tsx— Codex option in worker tool selection with installed state detectionsrc/hooks/useIntegrationManagement.ts— Codex integration status hooksrc/components/IntegrationList/index.tsx— Codex entry in integration listFiles Changed:
backend/app/controller/tool_controller.pybackend/app/utils/toolkit/codex_toolkit.py(new)server/app/model/config/config.pyserver/app/type/config_group.pysrc/components/AddWorker/ToolSelect.tsxsrc/components/IntegrationList/index.tsxsrc/hooks/useIntegrationManagement.tssrc/pages/Setting/MCP.tsxWhat is the purpose of this pull request?