Store the rotating refresh token in a file, and rewrite the README - #1
Merged
Conversation
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>
There was a problem hiding this comment.
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.shnow 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.shadds-ras an alias for--refresh.README.mdis 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.
| # 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 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two related commits: the behaviour change, and the docs that describe it.
9dbedfc— store the rotating refresh token in a file the helper ownsOkta 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'senvironment, 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.shnow owns~/.claude/.hms_refresh_token(mode600, overridewith
HMS_REFRESH_TOKEN_FILE) and rewrites it after every login, preferring thefile over the variable.
HMS_REFRESH_TOKENis kept only to bootstrap the file ona first run. Alongside that:
mkdirlock serialises concurrent runs, since Claude Code may invoke thehelper 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.
HMS_USERNAME/HMS_PASSWORD, and apassword login's returned refresh token is saved — so the setup re-heals
itself rather than needing a manual re-seed.
mktemp+mv, so the file is never left half-written;reads strip whitespace, so a stray newline can't corrupt it.
--data-urlencode, so passwords and tokenscontaining
&,+or%survive the round trip.get-okta-token.shgains-ras an alias for--refresh.edda0eb— rewrite the README for readabilityNo 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
rewrite are easier to review in sequence than as one blob.
bash -n, which catchessyntax errors only. Neither has been executed — that needs HMS credentials and
the VPN. The rotation and locking behaviour is therefore unverified at
runtime.
and run
./hms-ai-token.sh && ./hms-ai-token.sh. Both runs must print atoken; that is precisely the case the old env-var approach failed.
restructuring didn't quietly drop a fact.
🤖 Generated with Claude Code