Skip to content

Store the rotating refresh token in a file, and rewrite the README - #1

Merged
nathan-palmer merged 2 commits into
mainfrom
refresh-token-file-and-readme
Jul 29, 2026
Merged

Store the rotating refresh token in a file, and rewrite the README#1
nathan-palmer merged 2 commits into
mainfrom
refresh-token-file-and-readme

Conversation

@nathan-palmer

Copy link
Copy Markdown
Contributor

Two related commits: the behaviour change, and the docs that describe it.

9dbedfc — store the rotating refresh token in a file the helper owns

Okta rotates refresh tokens. Spending one returns a replacement and retires the
original, so a refresh token is single-use — which means it could never reliably
live in HMS_REFRESH_TOKEN. A script can't write to its parent shell's
environment, so the next run replayed a token Okta had already retired: the
helper worked once or twice, then failed with invalid_grant.

hms-ai-token.sh now owns ~/.claude/.hms_refresh_token (mode 600, override
with HMS_REFRESH_TOKEN_FILE) and rewrites it after every login, preferring the
file over the variable. HMS_REFRESH_TOKEN is kept only to bootstrap the file on
a first run. Alongside that:

  • An mkdir lock serialises concurrent runs, since Claude Code may invoke the
    helper several times at once and two logins would otherwise invalidate each
    other's token. Locks left behind by a crashed run go stale after 2 minutes.
  • A rejected refresh token falls back to HMS_USERNAME/HMS_PASSWORD, and a
    password login's returned refresh token is saved — so the setup re-heals
    itself rather than needing a manual re-seed.
  • Writes go through mktemp + mv, so the file is never left half-written;
    reads strip whitespace, so a stray newline can't corrupt it.
  • Credentials are sent with --data-urlencode, so passwords and tokens
    containing &, + or % survive the round trip.

get-okta-token.sh gains -r as an alias for --refresh.

edda0eb — rewrite the README for readability

No documented facts, URLs, model IDs, or script behaviours changed here; the
edits are structural. The rotation explanation appeared three times at
near-full length and is now consolidated into one section the others link to.
The hand-maintained TOC became an at-a-glance table of base URL, model ID,
endpoints, auth header, and prerequisites. The VPN and username-vs-email
gotchas moved ahead of the quickstart, since both block you before the first
command. Reference-only curl invocations are collapsed into <details>.

Review notes

  • Kept as two commits deliberately: a 172-line doc reshuffle and a token-storage
    rewrite are easier to review in sequence than as one blob.
  • Verification is incomplete. Both scripts pass bash -n, which catches
    syntax errors only. Neither has been executed — that needs HMS credentials and
    the VPN. The rotation and locking behaviour is therefore unverified at
    runtime.
  • Suggested check before merging: on a real machine, seed the refresh token
    and run ./hms-ai-token.sh && ./hms-ai-token.sh. Both runs must print a
    token; that is precisely the case the old env-var approach failed.
  • Worth a second pair of eyes on the README diff specifically, to confirm the
    restructuring didn't quietly drop a fact.

🤖 Generated with Claude Code

nathan-palmer and others added 2 commits July 29, 2026 15:05
Restructure without changing any documented facts, URLs, model IDs, or
script behaviour:

- consolidate the refresh-token rotation explanation, which appeared three
  times, into a single "Refresh tokens" section that the other mentions link to
- replace the hand-maintained TOC with an "At a glance" table of the base URL,
  model ID, endpoints, auth header, and prerequisites
- pull the VPN and username-vs-email gotchas out of the quickstart into their
  own section, since both block you before the first command
- rename sections to actions ("Step 1 - Get a token") and add an A/B comparison
  table so the Claude Code setup choice is visible before the walkthroughs
- tabulate the three AuthN/AuthZ/Inference phases with the error code each
  produces, and renumber Option B as discrete steps
- collapse the raw ROPC curl and by-hand refresh flow into <details>
- state the OpenAI routes and model ID plainly instead of deferring to the
  platform team to confirm them

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Okta rotates refresh tokens: spending one returns a replacement and retires
the original. Holding it in HMS_REFRESH_TOKEN could therefore only ever work
once or twice, since a script cannot write to its parent shell's environment
and the next run replayed a retired token.

hms-ai-token.sh now owns ~/.claude/.hms_refresh_token (mode 600, override with
HMS_REFRESH_TOKEN_FILE) and rewrites it after every login, preferring the file
over the variable; HMS_REFRESH_TOKEN is kept only to bootstrap the file on a
first run. Alongside that:

- serialise concurrent runs with an mkdir lock, since Claude Code may invoke
  the helper several times at once and two logins would otherwise invalidate
  each other's token; locks left by a crashed run go stale after 2 minutes
- fall back to HMS_USERNAME/HMS_PASSWORD when a stored refresh token is
  rejected, and save the refresh token a password login returns, so the setup
  re-heals itself instead of needing a manual re-seed
- write the token via mktemp + mv so the file is never left half-written, and
  strip whitespace on read so a stray newline can't corrupt it
- send credentials with --data-urlencode so passwords and tokens containing
  '&', '+' or '%' survive the round trip

get-okta-token.sh gains -r as an alias for --refresh.

Behaviour documented in README.md, committed separately.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 29, 2026 19:15

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request updates the Okta-token helper tooling to persist rotating refresh tokens to disk (instead of relying on an environment variable), and restructures the README to better explain setup and the refresh-token rotation model.

Changes:

  • hms-ai-token.sh now stores the rotating Okta refresh token in a helper-owned file with locking and atomic writes, and falls back to username/password when refresh fails.
  • get-okta-token.sh adds -r as an alias for --refresh.
  • README.md is reorganized for readability, with consolidated guidance on refresh tokens and Claude Code configuration.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
README.md Restructures documentation and consolidates refresh-token rotation guidance and setup steps.
hms-ai-token.sh Implements refresh-token file persistence with locking + atomic updates; adds self-healing refresh/password flow.
get-okta-token.sh Adds -r alias parsing for refresh-token output.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread hms-ai-token.sh
# Extra login arguments are passed in; --data-urlencode escapes the values, so
# passwords and tokens containing '&', '+' or '%' are sent correctly.
okta_post() {
curl --silent --show-error --request POST \
Comment thread get-okta-token.sh
Comment on lines 44 to +47
WANT_REFRESH=false
if [ "$1" = "--refresh" ]; then
WANT_REFRESH=true
fi
case "$1" in
-r|--refresh) WANT_REFRESH=true ;;
esac
@nathan-palmer
nathan-palmer merged commit 39f9d43 into main Jul 29, 2026
1 check passed
@nathan-palmer
nathan-palmer deleted the refresh-token-file-and-readme branch July 29, 2026 19:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants