codex-oauth 0.1.0

OAuth login for OpenAI Codex (ChatGPT account)
Documentation
# codex-oauth

PKCE OAuth login for OpenAI Codex — obtains an access token via a browser-based login against `auth.openai.com`, usable as a Bearer token with the ChatGPT backend API.

- crates.io: https://crates.io/crates/codex-oauth
- GitHub: https://github.com/motosan-dev/motosan-ai

## Install

```toml
[dependencies]
codex-oauth = "0.1"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
```

## Usage

### Login

```rust
#[tokio::main]
async fn main() -> Result<(), codex_oauth::Error> {
    let token = codex_oauth::login().await?;
    println!("{}", token.access_token);
    Ok(())
}
```

`login()` opens the browser to `auth.openai.com` (and prints the URL for manual opening) then listens on `http://localhost:1455/auth/callback` for the redirect. Times out after 120 seconds.

### Refresh

```rust
let new_token = codex_oauth::refresh(&token.refresh_token).await?;
```

### Expiry check

```rust
if token.is_expired() {
    let token = codex_oauth::refresh(&token.refresh_token).await?;
}
```

### Persist to disk

`Token` implements `serde::Serialize` / `Deserialize`:

```rust
let json = serde_json::to_string(&token)?;
// later:
let token: codex_oauth::Token = serde_json::from_str(&json)?;
```

### Use with OpenAI provider (motosan-ai)

```rust
let token = codex_oauth::login().await?;

let client = motosan_ai::Client::builder()
    .provider(motosan_ai::Provider::OpenAI)
    .api_key(token.access_token)
    .base_url("https://chatgpt.com/backend-api")
    .build()?;
```

## Notes

- Port `1455` must be free — it is hardcoded by OpenAI's app registration.
- `CLIENT_ID` is OpenAI's public Codex app registration (`app_EMoamEEZ73f0CkXaXp7hrann`) and is not configurable.
- Requires a ChatGPT account.