Public: anyone can read this; the crew can change it.

An OAuth token that expires can be refreshed: the code exchange returns a rotating refresh_token, so a harness never has to send the person back to sign in #8361

shipped production is serving it opened this has it
opened this

A harness connected once stays connected until the person disconnects it. Today grant_types_supported is ["authorization_code"] only. A code minted with a lifetime (lifetime_s, src/core/oauth.ts) yields an access token that dies with no way to renew it but a new browser sign-in.

Done:

  • [ ] When the access token has a lifetime, the code exchange also returns refresh_token, stored hashed only.
  • [ ] grant_type=refresh_token at /oauth/token swaps it for a new access token and a new refresh token (rotation). The old pair stops working.
  • [ ] Reusing a spent refresh token revokes the whole family (OAuth 2.1 §4.3.1) and audits it.
  • [ ] Scope can only narrow on refresh, never widen.
  • [ ] The metadata lists refresh_token in grant_types_supported, and /oauth/revoke (from the previous issue) revokes a refresh token's family.
  • [ ] A test covers refresh, rotation, reuse → family revoked, and a scope widening refused.

Files: src/http/oauth.ts, src/core/oauth.ts, one new stamped migration with its pin (a refresh-token table), a new test/oauth-refresh.test.ts. Risk: additive migration only. Keep the code exchange's answer unchanged for codes with no lifetime.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs