Skip to content

keryx auth

Run a platform's interactive OAuth flow and store its access token, so posting "just works" without hand-cranking the API. Instagram is the first platform.

keryx auth <platform>                          # e.g. keryx auth instagram
keryx auth instagram --redirect <uri>          # pin a specific registered redirect
keryx auth instagram --redirect <uri> --code <code>   # exchange a pasted code (non-interactive)

Instagram

keryx auth instagram runs the Instagram Login OAuth flow — no --redirect needed in the common case:

  1. Auto-selects a free loopback port from the registered range (https://localhost:3764/:3769/) and prints the chosen callback.
  2. Prints (and tries to open) the authorize URL with the scopes keryx needs, including instagram_business_content_publish.
  3. Captures the returned code from whichever comes first:
  4. a loopback callback server bound to all interfaces on the chosen port — so the browser reaches it via localhost, an SSH port-forward, or the host's LAN IP. It auto-captures the code (nothing to copy). Meta requires an https redirect, so the server serves TLS with an in-memory self-signed cert; the browser warns once that the cert is untrusted — proceeding is safe (a local-only, throwaway cert). See Certificate trust.
  5. a code pasted on stdin — the fallback for a box the browser can't reach. Both paths run together; first to arrive wins.
  6. Exchanges code → short-lived → long-lived (~60-day) token.
  7. Stores the token: the OS keychain on a desktop, else the config file (a headless dev server / CI has no keychain). Writes platforms.instagram.user_id, redirect_uri + enabled. The token is never printed.

Flags

  • --redirect <uri> — pin a specific OAuth redirect URI instead of auto-selecting. Must be one of the URIs registered in the Meta app. Use this to force a port, or for a non-loopback redirect.
  • --code <code> — skip the interactive step and exchange a code you copied from the browser's address bar directly. Pair with --redirect set to the same URI the code was issued for.

Prerequisites

  • platforms.instagram.app_id set (the Instagram app ID).
  • INSTAGRAM_APP_SECRET in the environment (the Instagram app secret).
  • The loopback redirect URIs registered in the Meta app (API setup with Instagram login → Business login settings). Meta rejects every non-https redirect, regardless of host, so register the https range https://localhost:3764/https://localhost:3769/. keryx picks the first free one; the range must stay in sync with loopbackPortRange in the code.

Typical run

keryx auth instagram
# → Using OAuth callback https://localhost:3764/
# → opens the authorize URL; approve consent (lists content publishing)
# → browser lands on https://localhost:3764/?code=… ; click through the
#   one-time cert warning; keryx captures + stores the token automatically.

On a remote box, port-forward first (ssh -L 3764:localhost:3764 …) or just hit the host's LAN IP — the callback binds all interfaces.

Manual fallback (--code)

If the browser can't reach the callback at all, keryx also prints the URL and waits for a pasted code:

  1. Open the authorize URL, approve, and let the browser land on https://localhost:<port>/?code=…#_ (it may show connection refused — the code is still in the address bar).
  2. Copy the code (between code= and #_) and run keryx auth instagram --redirect https://localhost:<port>/ --code <code>, using the same port the authorize URL used.

The code is single-use and expires in minutes — grab it and exchange promptly.

Certificate trust

Today the callback presents an in-memory self-signed cert, so the browser shows a one-time "untrusted certificate" warning — safe to click through, since the cert is local-only and regenerated each run. A future (pre-v1) enhancement will add a keryx init hook to install a phpboyscout-signed trusted root CA (opt-in), so the callback cert is trusted and the warning disappears.

See the how-to: Get Instagram posting credentials.

Token resolution

The Instagram publisher reads its token in this order: INSTAGRAM_ACCESS_TOKEN env (CI / manual override) → OS keychainconfig file. auth refresh (rotate before the ~60-day expiry, alert on failure) is the next piece.