Deployment

Apr 2026

Connecting JobPilot to ChatGPT with Device Authorization

A code-level look at JobPilot's ChatGPT device authorization flow, token storage and refresh, per-user isolation, and authenticated calls to the Codex response endpoint.

2 min read

M.Behbahani

openAI

JobPilot lets an authenticated user connect a ChatGPT account and use that authorization for task-agent work. The interesting part is not the Connect button. It is the device authorization lifecycle behind it: issue a user code, poll for approval, exchange the authorization code, isolate tokens by JobPilot user, refresh expired access, and keep credentials away from the browser.

The implementation is in src/lib/convex/openai.ts, the connection schema is in src/lib/convex/schema.ts, and the model adapter is in src/lib/convex/support/llmProvider.ts.

The implemented authorization flow

%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#111827', 'primaryTextColor': '#F9FAFB', 'primaryBorderColor': '#60A5FA', 'lineColor': '#94A3B8', 'secondaryColor': '#1F2937', 'tertiaryColor': '#0F172A', 'fontSize': '15px'}}}%% sequenceDiagram actor User participant UI as JobPilot UI participant CVX as Convex action participant AUTH as auth.openai.com participant DB as openaiConnections participant CODEX as Codex responses endpoint User->>UI: Connect ChatGPT UI->>CVX: initiateDeviceAuth CVX->>AUTH: Request device user code AUTH-->>CVX: deviceAuthId, userCode, interval CVX-->>UI: Verification URL and code User->>AUTH: Approve code UI->>CVX: pollDeviceAuth CVX->>AUTH: Poll and exchange authorization code AUTH-->>CVX: Access, refresh, and ID tokens CVX->>DB: Store tokens under authenticated user ID UI->>CVX: Run task agent CVX->>CODEX: Bearer token and account context

initiateDeviceAuth requests the user code. pollDeviceAuth treats pending responses separately from failures, then exchanges the approved code for tokens. getValidAccessToken refreshes an expiring token with a 60-second safety buffer.

Run the connection from JobPilot

  1. Sign in to JobPilot.

  1. Open Connections and start the ChatGPT connection.

  1. JobPilot opens the authorization page for the connected ChatGPT account. Complete the account sign-in method shown there.

  1. If device authorization is disabled for the account, follow the security-settings link shown by the provider, enable it, and restart the flow.

  1. Copy the displayed security code and approve it on the authorization page.

  1. Return to JobPilot and wait for the connected status.

The browser receives connection status, account email, plan type, and expiry state. It does not receive the stored access or refresh token.

Security and reuse points

The openaiConnections table is indexed by the authenticated JobPilot user ID. Server-side actions retrieve and refresh tokens, while the public status query omits both token values. Before adapting this pattern, add token encryption appropriate to your persistence layer, audit disconnect and revocation behavior, and confirm the provider's current authorization and API requirements.

The model adapter also sets store=false, supplies the ChatGPT account ID when available, and converts system messages into the instructions field expected by the response endpoint. Those details belong in code and tests because they can change independently of the connection UI.

Inspect the working flow

Share this post http://www.oploy.eu/blog/connecting-chatgpt-to-apps/ Copied!