Codex OAuth Automation Extension
Skill by
ara.so
— Daily 2026 Skills collection.
A Chrome extension that automates the full OpenAI OAuth registration/login flow including email verification, CPA callback handling, and multi-round batch execution. Supports DuckDuckGo, QQ Mail, 163 Mail, and Inbucket as verification code sources.
Installation
Clone the repository:
git
clone https://github.com/QLHazyCoder/codex-oauth-automation-extension.git
cd
codex-oauth-automation-extension
Load in Chrome:
Navigate to
chrome://extensions/
Enable
Developer mode
(top right toggle)
Click
Load unpacked
Select the project directory
Open the side panel from the Chrome toolbar to configure and run.
Project Structure
background.js # Main orchestrator: steps 1–9, tab management, state
manifest.json # Extension manifest
data/names.js # Random name/birthday data
content/utils.js # Shared helpers: waitForElement, click, stop control
content/vps-panel.js # CPA panel: Step 1 / Step 9
content/signup-page.js # OpenAI signup/login: Steps 2/3/5/6/8
content/duck-mail.js # DuckDuckGo @duck.com address generation
content/qq-mail.js # QQ Mail OTP polling
content/mail-163.js # 163 Mail OTP polling
content/inbucket-mail.js # Inbucket mailbox OTP polling
sidepanel/ # Sidebar UI (HTML/CSS/JS)
Configuration (Side Panel Fields)
Field
Description
Example
CPA
Your OAuth management panel URL
https://your-host/management.html#/oauth
Mail
Verification code source
163 Mail
,
QQ Mail
, or
Inbucket
Email
Registration email (or click Auto for @duck.com)
user@duck.com
Password
Custom password; leave blank to auto-generate
MyPass123!
Inbucket
Inbucket host (only when Mail=Inbucket)
your-inbucket-host
Mailbox
Inbucket mailbox name (only when Mail=Inbucket)
tmp-mailbox
Storage Behavior
chrome.storage.session
— runtime state (steps, OAuth link, email, password, callback URL, tab info). Cleared when browser closes.
chrome.storage.local
— persistent config (CPA URL, password, mail service, Inbucket settings). Survives browser restarts.
The 9-Step Workflow
Step 1: Get OAuth Link
Opens CPA panel → finds
Codex OAuth
card → clicks login → extracts authorization URL → saves to
OAuth
field.
Step 2: Open Signup
Opens the OAuth authorization link → locates and clicks
Sign up / Register / 创建账户
button.
Step 3: Fill Email / Password
Fills registration form with email and password. Auto-generates strong password if field is blank. Actual password used is written back to the sidebar.
Step 4: Get Signup Code
Polls the configured mailbox for a 6-digit OTP. Handles
Operation timed out
errors by auto-clicking retry.
Email matching rules:
Sender contains:
openai
,
noreply
,
verify
,
auth
,
duckduckgo
,
forward
Subject contains:
verify
,
verification
,
code
,
验证
,
confirm
Step 5: Fill Name / Birthday
Generates random name and birthday. Handles two page variants:
Birthday mode: fills year/month/day
Age mode: fills
input[name='age']
directly
Step 6: Login via OAuth
Re-fetches latest CPA OAuth link, then logs in with the newly registered account.
Step 7: Get Login Code
Same as Step 4 but with login-specific keyword matching.
Step 8: Manual OAuth Confirm (Auto-attempts)
Locates the "Continue/Authorize" button on the OAuth consent page
Uses Chrome
debugger
API to dispatch input events for the click
Monitors
chrome.webNavigation.onBeforeNavigate
for localhost callback
Only accepts:
http(s)://localhost:Timeout waiting for:
${
selector
}
)
;
}
Reading/Writing Session State (background.js pattern)
// Save OAuth link to session
await
chrome
.
storage
.
session
.
set
(
{
oauthLink
:
extractedUrl
}
)
;
// Read current email and password
const
{
currentEmail
,
currentPassword
}
=
await
chrome
.
storage
.
session
.
get
(
[
'currentEmail'
,
'currentPassword'
]
)
;
// Update step status
await
chrome
.
storage
.
session
.
set
(
{
stepStatus
:
{
...
existingStatus
,
step3
:
'done'
}
}
)
;
Sending Messages to Content Scripts
// background.js → content script
const
[
tab
]
=
await
chrome
.
tabs
.
query
(
{
url
:
'://chat.openai.com/*'
}
)
;
const
result
=
await
chrome
.
tabs
.
sendMessage
(
tab
.
id
,
{
action
:
'FILL_EMAIL'
,
email
:
'user@duck.com'
,
password
:
'GeneratedPass1!'
}
)
;
Inbucket Mailbox Polling (content/inbucket-mail.js pattern)
// Only targets unread messages
const
unseenEntries
=
document
.
querySelectorAll
(
'.message-list-entry.unseen'
)
;
// From 2nd poll onwards, click the refresh button
if
(
pollCount
1 ) { const refreshBtn = document . querySelector ( '[data-action="refresh"]' ) ; if ( refreshBtn ) refreshBtn . click ( ) ; await sleep ( 1000 ) ; } // After reading, delete the email to avoid re-matching Chrome Debugger Click (content/signup-page.js pattern) // Attach debugger to tab for synthetic input events await chrome . debugger . attach ( { tabId } , '1.3' ) ; const { x , y } = buttonBounds ; await chrome . debugger . sendCommand ( { tabId } , 'Input.dispatchMouseEvent' , { type : 'mousePressed' , x , y , button : 'left' , clickCount : 1 } ) ; await chrome . debugger . sendCommand ( { tabId } , 'Input.dispatchMouseEvent' , { type : 'mouseReleased' , x , y , button : 'left' , clickCount : 1 } ) ; await chrome . debugger . detach ( { tabId } ) ; OAuth Callback Listener (background.js pattern) chrome . webNavigation . onBeforeNavigate . addListener ( async ( details ) => { // Only main frame, only the auth tab if ( details . frameId !== 0 ) return ; if ( details . tabId !== authTabId ) return ; const url = details . url ; // Strict: must be localhost /auth/callback with code + state if ( / ^ https ? : \/ \/ localhost: \d + \/ auth \/ callback \? / . test ( url ) ) { const parsed = new URL ( url ) ; if ( parsed . searchParams . get ( 'code' ) && parsed . searchParams . get ( 'state' ) ) { await chrome . storage . session . set ( { callbackUrl : url } ) ; } } } ) ; Stop Signal Broadcasting // From sidebar: send stop await chrome . runtime . sendMessage ( { action : 'STOP_FLOW' } ) ; // In background.js: set flag and broadcast to all content scripts await chrome . storage . session . set ( { stopFlow : true } ) ; const tabs = await chrome . tabs . query ( { } ) ; for ( const tab of tabs ) { chrome . tabs . sendMessage ( tab . id , { action : 'STOP_FLOW' } ) . catch ( ( ) => { } ) ; } DuckDuckGo Email Auto-Fetch // Triggered by sidebar "Auto" button next to Email field // content/duck-mail.js opens: // https://duckduckgo.com/email/settings/autofill // Looks for existing private address or generates new one const generateBtn = document . querySelector ( '[data-testid="generate-address"]' ) ; if ( generateBtn ) generateBtn . click ( ) ; await waitForElement ( '.address-display' ) ; const newAddress = document . querySelector ( '.address-display' ) . textContent . trim ( ) ; Persistent Config (chrome.storage.local) // Save config await chrome . storage . local . set ( { cpaUrl : 'https://your-host/management.html#/oauth' , mailService : 'Inbucket' , // '163 Mail' | 'QQ Mail' | 'Inbucket' inbucketHost : 'your-inbucket-host' , inbucketMailbox : 'tmp-mailbox' , customPassword : '' , // empty = auto-generate } ) ; // Load config const config = await chrome . storage . local . get ( [ 'cpaUrl' , 'mailService' , 'inbucketHost' , 'inbucketMailbox' , 'customPassword' ] ) ; Troubleshooting Step 8 timeout (120s exceeded) The OAuth consent page structure may have changed Manually click the "Continue" button and observe what URL the redirect hits Check the button selector in content/signup-page.js Step 4/7: OTP never arrives Verify the mail service tab is open and logged in before running For Inbucket: confirm https://
/m/ / is accessible Check sender/subject filters — OpenAI sometimes changes sender addresses For QQ/163: ensure the webmail tab is the correct account Duck email auto-fetch fails (retries 5x then pauses) DuckDuckGo extension must be installed and logged in The autofill settings page URL may have changed Fall back to manual email entry in the sidebar CPA panel not detected (Step 1/9) Confirm your CPA URL matches management.html#/oauth path structure The content/vps-panel.js selectors are hardcoded to a specific panel layout Try running Step 1 manually to see console errors "Operation timed out" on signup (Step 4) This is handled automatically — the script clicks the retry button and re-submits If it loops, the OpenAI signup endpoint may be rate-limiting your IP Tab cleanup issues Old localhost tabs accumulate: Step 9 only cleans http://localhost:1455/auth* If your CPA uses a different port, update the cleanup filter in background.js Recommended Workflow 1. Configure sidebar (CPA URL, Mail service, credentials) 2. Run Step 1 manually → verify OAuth link appears 3. Run Steps 2-4 manually → confirm email + OTP flow works 4. If successful, enable Auto with N=5 for a test batch 5. Scale up rounds once flow is stable Note: Always test single-step flow before enabling Auto. The most fragile steps are Step 8 (OAuth consent click) and Step 4/7 (OTP timing). Use Inbucket for most reliable OTP delivery in automated runs.