Skip to content

fix(coderd/httpmw): honor fixed lifetime for CLI API tokens#26376

Merged
jdomeracki-coder merged 1 commit into
mainfrom
fix/token-fixed-lifetime
Jun 15, 2026
Merged

fix(coderd/httpmw): honor fixed lifetime for CLI API tokens#26376
jdomeracki-coder merged 1 commit into
mainfrom
fix/token-fixed-lifetime

Conversation

@jdomeracki-coder

Copy link
Copy Markdown
Contributor

What

API key validation applied a sliding-window expiry refresh to every key type. Programmatic API tokens (created via coder tokens create, login type token) had their expires_at extended to now + lifetime on each authenticated request (with a ~1h debounce), so a token used within its lifetime window never actually expired.

This restricts the sliding-window refresh to interactive login sessions (password / OIDC / GitHub). Programmatic tokens now honor their fixed expires_at.

Why

A finite token --lifetime is expected to be a hard expiry. Silently extending it on use defeats that expectation and prevents rotation of long-lived automation credentials.

Changes

  • coderd/httpmw/apikey.go: skip the expiry refresh when key.LoginType == database.LoginTypeToken.
  • coderd/httpmw/apikey_test.go: regression test asserting a token's expiry is not extended on use.

Notes

  • Interactive sessions are unaffected (they still slide while active).
  • Tokens already extended are not retroactively shortened; this prevents future extension.
Validation
  • go build ./coderd/httpmw/...
  • go test ./coderd/httpmw/ -run TestAPIKey -count=1 (all pass, including the new TokenNoExpiryRefresh and the interactive ValidUpdateExpiry)
  • golangci-lint run ./coderd/httpmw/ (clean)
  • Confirmed the new test fails without the production change and passes with it.

🤖 Generated by Coder Agents on behalf of @jdomeracki-coder.

API key validation applied a sliding-window expiry refresh to every key type. Programmatic API tokens (created via `coder tokens create`, LoginType token) had their expires_at extended to now+lifetime on each authenticated request, so a token used within its lifetime window never expired.

Restrict the refresh to interactive login sessions (password, OIDC, GitHub). Programmatic tokens now honor their fixed expires_at.

Copy link
Copy Markdown
Contributor Author

For changelog / docs (follow-up): when this ships, please surface the following breaking-change callout in the release notes and the token management docs.

Warning

Behavior change: API tokens now honor their fixed --lifetime.
Previously, tokens created with coder tokens create were silently extended on each use (sliding-window refresh) and never expired while in active use. After upgrading, programmatic tokens expire at created_at + lifetime. Scripts or CI relying on the old never-expire behavior will break once the token reaches its original expiry. Recreate them with an appropriate --lifetime (and rotate on a schedule).


🤖 Generated by Coder Agents on behalf of @jdomeracki-coder.

@jdomeracki-coder jdomeracki-coder merged commit 450ddff into main Jun 15, 2026
64 checks passed
@jdomeracki-coder jdomeracki-coder deleted the fix/token-fixed-lifetime branch June 15, 2026 16:46
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 15, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

backport security Area: security

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants