Skip to content

keryx auth refresh

Description

Keep unattended posting alive: refresh/rotate each platform's tokens where it can, and alert where it can't (spec 0010-auth-refresh.md). Run it on a schedule in the owning project, well inside each token's window — a silently stale token is the top unattended failure mode.

Per platform, by token shape:

Platform Action
Instagram refresh-in-place near expiry (new ~60-day token)
YouTube health-check the durable refresh token
TikTok rotate the refresh token + persist the new one
LinkedIn can't refresh (standard app) → alert: re-auth by DATE

It is side-effecting (writes tokens) and so is gated off the MCP surface.

Usage

keryx auth refresh [<platform>|all] [--dry-run]
  • keryx auth refresh / keryx auth refresh all — every enabled platform (the CI entrypoint).
  • keryx auth refresh tiktok — one platform.
  • --dry-run — report each platform's token status + the action it would take; change nothing.

Exits non-zero if any platform needs attention (so a scheduled pipeline goes red), and fires the configured alert backend.

Configuration

Both backends are config-selected (auth.*), like keryx's generation providers — pick the one that suits your infra; adding another is purely additive.

auth:
  writeback:
    backend: local        # local (keychain/config) | gitlab (CI variable API)
    # gitlab:
    #   project: "phpboyscout/blog"   # or CI_PROJECT_ID in a pipeline
    #   api_url: "https://gitlab.com/api/v4"   # or CI_API_V4_URL
  alerts:
    backend: none         # none (red pipeline only) | webhook | email
    # webhook:
    #   url: ""           # or ALERT_WEBHOOK_URL
    # email:
    #   host: smtp.example.com
    #   port: 587
    #   from: keryx@phpboyscout.uk
    #   to: ["matt@phpboyscout.uk"]

Write-back — where refreshed tokens land

  • local (default) — the OS keychain, else the config file. For CLI use.
  • gitlab — updates the project's CI/CD variable (the same masked, protected variable the publisher reads, e.g. TIKTOK_REFRESH_TOKEN) via the GitLab API, so the next scheduled run sees the rotated token. This is what makes the unattended path work — an ephemeral CI job otherwise can't write back the variables it read. Needs GITLAB_TOKEN (a project/group access token, api scope — CI_JOB_TOKEN can't write variables). project/api_url default to the predefined CI_PROJECT_ID/CI_API_V4_URL in a pipeline. The variable must already exist (masked + protected) — the backend updates its value, it never creates a new, unmasked secret.

Alerts — where a "needs attention" goes

A non-zero exit (red pipeline) is always on; the notifier adds an out-of-band ping.

  • none (default) — rely on the red pipeline only.
  • webhook — POST to a Slack/Teams/Discord incoming webhook (auth.alerts.webhook.url or ALERT_WEBHOOK_URL).
  • email — send over SMTP. Host/port/from/to from config; credentials from ALERT_SMTP_USERNAME / ALERT_SMTP_PASSWORD. Port defaults to 587.

Secrets are resolved as for posting (env → keychain → config); the same client ids/secrets the adapters use (TIKTOK_CLIENT_SECRET, YOUTUBE_CLIENT_SECRET, INSTAGRAM_APP_SECRET, LINKEDIN_CLIENT_SECRET) are needed to refresh.

Flags

Flag Description Default Required
--dry-run validate only, report token status without changing anything false

Scheduling

keryx is stateless — the schedule lives in the owning project's CI (a weekly scheduled pipeline running keryx auth refresh all with auth.writeback.backend set for that environment). See spec 0010 §8.