pig_protocol/oauth/codex

OpenAI Codex (ChatGPT) OAuth PKCE flow — pure request/response construction.

This mirrors the OAuth client used by the official Codex CLI and IDE extensions so that pig_proxy can obtain and refresh Codex credentials itself, without shelling out to codex login.

No network access happens in this module. Callers (e.g. pig_proxy/codex_login, pig_proxy/codex_refresh) build a request with the functions here, execute it with their own HTTP client, and feed the response body back into parse_token_response.

Types

A completed device authorization: the code + verifier to exchange.

pub type DeviceToken {
  DeviceToken(authorization_code: String, code_verifier: String)
}

Constructors

  • DeviceToken(authorization_code: String, code_verifier: String)

A device user-code response: the code to display + how often to poll.

pub type DeviceUserCode {
  DeviceUserCode(
    device_auth_id: String,
    user_code: String,
    interval_seconds: Int,
  )
}

Constructors

  • DeviceUserCode(
      device_auth_id: String,
      user_code: String,
      interval_seconds: Int,
    )

A PKCE verifier/challenge pair (RFC 7636).

Opaque so callers cannot construct mismatched verifier/challenge pairs (which would break the PKCE security guarantee). Use generate_pkce to create a pair and verifier/challenge to read the components.

pub opaque type Pkce

A parsed OAuth token endpoint response.

refresh_token is optional: per RFC 6749 §6 the authorization server MAY issue a new refresh token on refresh but is not required to. When absent, callers must retain their existing refresh token.

pub type TokenResponse {
  TokenResponse(
    access_token: String,
    refresh_token: option.Option(String),
    expires_in: Int,
  )
}

Constructors

  • TokenResponse(
      access_token: String,
      refresh_token: option.Option(String),
      expires_in: Int,
    )

Values

pub const auth_base_url: String
pub fn authorize_url(
  pkce: Pkce,
  state: String,
  redirect_uri: String,
  originator: String,
) -> String

Build the browser authorization URL for a login attempt.

originator identifies the calling application to OpenAI (the Codex CLI uses "codex_cli_rs"; pig_proxy should use its own name).

pub fn challenge(pkce: Pkce) -> String

The challenge embedded in the authorization URL.

pub const client_id: String

The public Codex CLI OAuth client id. Shared by the official Codex CLI and IDE extensions — it is a public PKCE client with no client secret.

pub const default_redirect_uri: String

Default local callback address used by the Codex CLI, pi, and pig_proxy’s login flow. Codex’s registered redirect URI is fixed to this value, so a custom port cannot be used.

pub const device_code_timeout_seconds: Int

How long a device code is valid (matches the official CLI / pi).

pub fn device_error_code(body: String) -> option.Option(String)

Extract the error code from a device token error response. The error field may be a string or an object with a code field; returns the code if either is present (used to tell deviceauth_authorization_pending / slow_down from a real failure).

pub const device_redirect_uri: String

Redirect URI used in the final code exchange for the device flow.

pub const device_request_content_type: String

Content-type for the device endpoints (JSON, unlike the token endpoint).

pub fn device_token_body(
  device_auth_id: String,
  user_code: String,
) -> String

JSON body for polling the device token endpoint.

pub fn device_token_url() -> String

Device token polling endpoint.

pub fn device_usercode_body() -> String

JSON body for the device user-code request.

pub fn device_usercode_url() -> String

Device user-code request endpoint (POST {client_id}).

pub const device_verification_uri: String

Where the user goes to enter the device code (in any browser).

pub fn exchange_request_body(
  code: String,
  verifier: String,
  redirect_uri: String,
) -> String

Form-encoded body for exchanging an authorization code for tokens.

pub fn generate_pkce() -> Pkce

Generate a fresh PKCE verifier and its SHA-256 challenge.

Uses a cryptographically secure RNG, so despite taking no arguments this function is not pure — each call produces different output.

pub fn generate_state() -> String

Generate a random CSRF state token for the authorization request.

pub fn parse_callback_query(
  query: String,
) -> Result(#(String, String), Nil)

Parse code and state out of a local callback’s query string (the part of the request after ?).

pub fn parse_device_token_success(
  body: String,
) -> Result(DeviceToken, json.DecodeError)

Parse a successful device token JSON response.

pub fn parse_device_usercode(
  body: String,
) -> Result(DeviceUserCode, json.DecodeError)

Parse a device user-code JSON response.

pub fn parse_token_response(
  body: String,
) -> Result(TokenResponse, json.DecodeError)

Parse a token (or refresh) endpoint JSON response body.

pub fn refresh_request_body(refresh_token: String) -> String

Form-encoded body for refreshing an access token.

pub const scope: String
pub const token_request_content_type: String

Content-type header value required by the token endpoint.

pub fn token_url() -> String

The OAuth token endpoint.

pub fn verifier(pkce: Pkce) -> String

The verifier to send in the token exchange request.

Search Document