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_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 token_request_content_type: String
Content-type header value required by the token endpoint.