codex-auth-helper-chrome-extension

v2026.09.25

Chrome extension for securely exporting ChatGPT session credentials to generate Codex-compliant auth.json configuration files locally

GitHub
Install command
npx skhub add reason-machines/codex-auth-helper-chrome-extension
Markdown
SKILL.md

Codex Auth Helper Chrome Extension

Skill by ara.so — Codex Skills collection.

Overview

Codex Auth Helper is a Chrome extension that securely exports your logged-in ChatGPT session credentials and generates a Codex-compliant auth.json configuration file. All processing happens 100% locally in the browser with no data sent to external servers.

Key Features:

  • Automatic ChatGPT session detection
  • Real-time token expiration countdown
  • Synthetic JWT id_token generation for Codex authentication
  • Local-only processing (no server uploads)
  • Support for Free/Plus/Pro account types

Installation

Developer Mode Installation

  1. Clone or download the repository:
git clone https://github.com/zhishile/codex-auth-helper.git
cd codex-auth-helper
  1. Open Chrome and navigate to chrome://extensions/

  2. Enable Developer mode (toggle in top-right corner)

  3. Click Load unpacked (top-left)

  4. Select the extension folder from the cloned repository

  5. Pin the extension to your toolbar for easy access

Verification

After installation, you should see the Codex Auth Helper icon in your Chrome toolbar. The extension requires these permissions:

  • downloads - to save the generated auth.json file
  • https://chatgpt.com/* - to read session credentials

Usage

Exporting auth.json

  1. Login to ChatGPT: Navigate to https://chatgpt.com/ and ensure you're logged in

  2. Open Extension: Click the Codex Auth Helper icon in your toolbar

  3. Verify Session: The popup will automatically detect your session and display:

    • Your profile avatar
    • Email address
    • Subscription tier (Free/Plus/Pro)
    • Token expiration countdown
  4. Generate Config: Click "生成并保存 auth.json" (Generate and Save auth.json)

  5. Download: The file will automatically download to your default downloads folder

auth.json Structure

The generated file follows this format:

{
  "user": "your-email@example.com",
  "access_token": "eyJhbGc...",
  "id_token": "synthetic-jwt-token",
  "expires_at": 1234567890,
  "account_type": "plus"
}

Fields:

  • user: Your ChatGPT account email
  • access_token: Session access token from cookies
  • id_token: Synthetically generated JWT for Codex authentication
  • expires_at: Unix timestamp when the token expires
  • account_type: free, plus, or pro

Extension Architecture

File Structure

extension/
├── manifest.json       # Extension configuration (Manifest V3)
├── popup.html         # UI interface
├── popup.js           # Frontend logic
├── background.js      # Service worker for token processing
├── styles.css         # Glassmorphism UI styling
└── icons/            # Extension icons

Key Components

manifest.json

{
  "manifest_version": 3,
  "name": "Codex 认证助手",
  "version": "1.0.0",
  "permissions": ["downloads"],
  "host_permissions": ["https://chatgpt.com/*"],
  "background": {
    "service_worker": "background.js"
  },
  "action": {
    "default_popup": "popup.html"
  }
}

Session Detection (popup.js pattern)

// Check ChatGPT login status
async function checkAuthStatus() {
  try {
    const response = await fetch('https://chatgpt.com/api/auth/session');
    const data = await response.json();
    
    if (data.user) {
      // User is logged in
      displayUserInfo({
        email: data.user.email,
        avatar: data.user.image,
        accountType: data.user.account_type || 'free'
      });
    } else {
      // Show login prompt
      showLoginButton();
    }
  } catch (error) {
    console.error('Auth check failed:', error);
  }
}

Token Extraction (background.js pattern)

// Extract tokens from cookies
chrome.cookies.getAll({
  domain: '.chatgpt.com'
}, (cookies) => {
  const accessToken = cookies.find(c => c.name === '__Secure-next-auth.session-token');
  
  if (accessToken) {
    // Generate synthetic JWT
    const syntheticToken = generateSyntheticJWT(accessToken.value);
    
    // Create auth.json structure
    const authConfig = {
      user: userEmail,
      access_token: accessToken.value,
      id_token: syntheticToken,
      expires_at: Math.floor(accessToken.expirationDate),
      account_type: accountType
    };
    
    // Trigger download
    downloadAuthFile(authConfig);
  }
});

Secure Local Download

function downloadAuthFile(authData) {
  // Convert to JSON
  const jsonString = JSON.stringify(authData, null, 2);
  
  // Create data URL (no blob storage)
  const dataUrl = 'data:application/json;charset=utf-8,' + 
                  encodeURIComponent(jsonString);
  
  // Trigger download
  chrome.downloads.download({
    url: dataUrl,
    filename: 'auth.json',
    saveAs: true
  });
}

Configuration

Customizing Export Behavior

You can modify popup.js to customize the export behavior:

// Custom filename with timestamp
const timestamp = new Date().toISOString().split('T')[0];
const filename = `auth_${timestamp}.json`;

chrome.downloads.download({
  url: dataUrl,
  filename: filename,
  saveAs: true // Set to false for automatic download
});

Token Refresh Handling

// Check token expiration
function checkTokenExpiry(expiresAt) {
  const now = Math.floor(Date.now() / 1000);
  const timeLeft = expiresAt - now;
  
  if (timeLeft < 3600) {
    // Less than 1 hour remaining
    showExpiryWarning('Token expires soon! Please re-login.');
  }
  
  // Update countdown display
  updateCountdown(timeLeft);
}

Integration with Codex

Using the Exported auth.json

After exporting, place auth.json in your Codex project directory:

# Typical Codex project structure
my-codex-project/
├── auth.json          # Place exported file here
├── codex.config.js
└── src/

Environment Variable Alternative

For sensitive environments, convert auth.json to environment variables:

# .env
CODEX_USER=your-email@example.com
CODEX_ACCESS_TOKEN=eyJhbGc...
CODEX_ID_TOKEN=synthetic-jwt-token
CODEX_ACCOUNT_TYPE=plus

Then reference in your Codex configuration:

// codex.config.js
module.exports = {
  auth: {
    user: process.env.CODEX_USER,
    access_token: process.env.CODEX_ACCESS_TOKEN,
    id_token: process.env.CODEX_ID_TOKEN,
    account_type: process.env.CODEX_ACCOUNT_TYPE
  }
};

Troubleshooting

Extension Not Detecting Session

Problem: Popup shows "Please login" even when logged into ChatGPT

Solutions:

  1. Refresh the ChatGPT tab and reopen the extension
  2. Clear ChatGPT cookies and re-login
  3. Check if you're on the correct domain (chatgpt.com not chat.openai.com)
  4. Verify extension has permission to access https://chatgpt.com/*
// Debug session detection
chrome.cookies.getAll({domain: '.chatgpt.com'}, (cookies) => {
  console.log('Found cookies:', cookies.map(c => c.name));
});

Token Expired Immediately

Problem: Generated auth.json shows token already expired

Solution: Re-login to ChatGPT to get fresh tokens:

// Check cookie expiration before export
if (cookie.expirationDate && cookie.expirationDate < Date.now() / 1000) {
  alert('Session expired. Please re-login to ChatGPT.');
  return;
}

Download Not Starting

Problem: "Generate and Save" button doesn't trigger download

Solutions:

  1. Check Chrome download permissions
  2. Verify downloads permission in manifest.json
  3. Check browser console for errors:
chrome.downloads.download({
  url: dataUrl,
  filename: 'auth.json',
  saveAs: true
}, (downloadId) => {
  if (chrome.runtime.lastError) {
    console.error('Download failed:', chrome.runtime.lastError);
  } else {
    console.log('Download started:', downloadId);
  }
});

Permission Denied Errors

Problem: Extension can't read cookies or trigger downloads

Solution: Reinstall with correct permissions:

{
  "permissions": ["downloads"],
  "host_permissions": ["https://chatgpt.com/*"],
  "optional_permissions": ["cookies"]
}

Security Best Practices

Safe Storage of auth.json

# Add to .gitignore
echo "auth.json" >> .gitignore

# Set restrictive permissions (Unix/Mac)
chmod 600 auth.json

Verify Extension Integrity

Before using, verify the extension only contains expected files:

# Check for unexpected network requests
grep -r "fetch\|XMLHttpRequest" extension/
grep -r "http" extension/ | grep -v "chatgpt.com"

Token Rotation

Implement automatic token refresh reminders:

// Set up expiry notification
function scheduleExpiryCheck(expiresAt) {
  const checkTime = (expiresAt - Math.floor(Date.now() / 1000) - 3600) * 1000;
  
  setTimeout(() => {
    chrome.notifications.create({
      type: 'basic',
      iconUrl: 'icons/icon128.png',
      title: 'Codex Auth Helper',
      message: 'Your ChatGPT token will expire soon. Please export a new auth.json.'
    });
  }, checkTime);
}

Common Patterns

Batch Export for Multiple Accounts

// Export with account identifier
function exportWithIdentifier(email) {
  const sanitizedEmail = email.replace('@', '_at_').replace('.', '_');
  const filename = `auth_${sanitizedEmail}.json`;
  
  chrome.downloads.download({
    url: dataUrl,
    filename: filename,
    saveAs: false
  });
}

Validation Before Export

function validateAuthData(authData) {
  const required = ['user', 'access_token', 'id_token', 'expires_at'];
  
  for (const field of required) {
    if (!authData[field]) {
      throw new Error(`Missing required field: ${field}`);
    }
  }
  
  if (authData.expires_at < Date.now() / 1000) {
    throw new Error('Token already expired');
  }
  
  return true;
}

Auto-Export on Login Detection

// Monitor for login events
chrome.webNavigation.onCompleted.addListener((details) => {
  if (details.url.includes('chatgpt.com')) {
    checkAuthStatus().then((isLoggedIn) => {
      if (isLoggedIn) {
        // Optionally auto-export
        showNotification('ChatGPT session detected. Ready to export.');
      }
    });
  }
});
Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.25

Published

Sep 25, 2026

Category

Uncategorized

License

NOASSERTION

Source path

skills/codex-auth-helper-chrome-extension

Default branch

main

Latest commit

901a4e3

Tree SHA

faa2fa4