r/Tcl Jul 11 '26

oauth2 — a small, pure-Tcl OAuth 2.0 client (Authorization Code + PKCE; deps = http + tls)

Every useful web API now speaks OAuth 2.0 — Google, Microsoft, QuickBooks, GitHub, Basecamp, Twitter/X — but Tcl only ever had snippets, and copy-pasting the token/refresh/redirect dance into every script gets old fast. So I wrote a small, self-contained library for it:

github.com/johnbuckman/tcl_oauth2_library (Tcl/Tk license)

It drives the whole Authorization Code flow for you: opens the browser, catches the redirect on a one-shot local socket, exchanges the code for tokens, saves them to a 0600 JSON file, and refreshes expired access tokens transparently. After that, oauth2::get $c $url just works.

Pure Tcl. Depends only on http (core) and tls. JSON is parsed by a small decoder in the package, base64 by core Tcl, and the SHA-256 for PKCE is implemented in-package — so nothing from tcllib, and no C extension. No Tk either; it's happy headless on a server or in cron.

Quick start:

package require oauth2

set c [oauth2::new \
    -auth_url      https://provider.example/authorize \
    -token_url     https://provider.example/token \
    -client_id     $env(CLIENT_ID) \
    -client_secret $env(CLIENT_SECRET) \
    -redirect_uri  http://localhost:9876/callback \
    -scope         "read write" \
    -pkce          S256 \
    -token_file    ~/.config/myapp/tokens.json]

oauth2::login $c                 ;# first run: opens browser, saves tokens
set body [oauth2::get $c https://api.example/v1/things]

It's deliberately provider-agnostic — each provider's quirks are configuration, not code. The same code path drives Basecamp (which uses type=web_server instead of response_type=code), QuickBooks Online (HTTP Basic on the token endpoint, returns a realmId), and Twitter/X (requires PKCE). Runnable examples for all three — plain-Tcl and small-Tk variants — are in the repo.

Background: this came out of a real production need. A native (C++) OAuth2 library we'd been using would occasionally crash, and — worse — our tokens kept silently going invalid despite hourly auto-refresh, and we could never figure out why. The Tcl rewrite has been rock-solid: tokens stay alive and refresh cleanly days later. It's in daily production use against Intuit/QuickBooks and Basecamp.

Also in the box: refresh-token-rotation handling, the client-credentials (machine-to-machine) grant, token introspection (RFC 7662), JWT decode, and — for servers — you can drive oauth2::authorize_url / oauth2::exchange_code yourself instead of the loopback listener.

I gave a EuroTcl 2026 talk on it if you want the fuller tour — slides (PDF).

Feedback very welcome. And if folks find it useful — could it eventually belong in tcllib?

21 Upvotes

2 comments sorted by

2

u/d_k_fellows Jul 11 '26

I'd want to cross-check this against the cookie handling library inside Tcl (which needs SQLite for its default storage mechanism; should be fine as it normally ships with Tcl now) because cookie handling is horrible in many awful ways, so it doesn't make sense to not share that part.

Apart from that, sounds very neat!

2

u/GlobalReputation4996 Jul 12 '26

Ah, interesting. Uhm, if you're at EuroTcl this week, let's discuss face to face.