litellm/tests/unit/proxy/anthropic_endpoints
devin-ai-integration[bot] 62dee3d730
feat(claude_code_gateway): issue rotating refresh tokens and a revocation endpoint (#44635)
* feat(claude_code_gateway): issue rotating refresh tokens and a revocation endpoint

The Claude Code gateway's device-code grant now returns a refresh token
alongside the session JWT, so a Claude Code session renews itself before
the JWT expires instead of forcing the user back through the browser sign-in.
grant_type=refresh_token re-mints the JWT from the live user row, rotates the
refresh token, and refuses a replayed, foreign, or identity-only token with
invalid_grant. The discovery document now advertises an RFC 7009 revocation
endpoint, which Claude Code's /logout calls with both tokens, so sign-out
burns the refresh token. The refresh token is the MCP gateway's sealed
session refresh token bound to the fixed client id claude_code, so both
front doors share one single-use record.

* fix(claude_code_gateway): mint the whole credential before claiming the device code

A refresh token that failed to mint answered 500 after the device code was
already claimed and the login deleted, so the client could not redeem the
completed sign-in again. The response is now built first, and the code is
claimed only when it is a 200.

* fix(claude-code-gateway): keep device sign-in working when session signing is unusable

* feat(claude-code-gateway): end the whole refresh chain on a replay or a revocation

* fix(mcp-gateway): fail the single-use peek closed on a Redis fault

* fix(mcp-gateway): read the single-use marker under the cache namespace

* fix(mcp-gateway): refuse a replayed refresh token without ending its chain

A refresh token presented a second time is refused as already used and
nothing else happens to the chain it was rotated from. Claude Code renews
from its in-memory copy of the credential, so a second terminal on the
same machine presents the token the first terminal already rotated and
then recovers from the shared credential file; ending the chain there
would sign both terminals out at every expiry. Only a revocation ends a
chain, so the 503-on-unrecorded-chain-ending path and its tests go away.

* fix(mcp-gateway): end the refresh chain before burning the revoked token

---------

Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
2026-10-06 20:57:50 -07:00
..
__init__.py test(proxy): move utils, agent_endpoints and endpoint tests into tests/unit/proxy (#44006) 2026-10-01 11:06:42 -07:00
test_claude_code_marketplace.py fix(security): remove the publicly known master key from the repo (#44718) 2026-10-06 10:55:24 -07:00
test_claude_code_skill_access.py fix(security): remove the publicly known master key from the repo (#44718) 2026-10-06 10:55:24 -07:00
test_endpoints.py test(proxy): move utils, agent_endpoints and endpoint tests into tests/unit/proxy (#44006) 2026-10-01 11:06:42 -07:00
test_gateway_endpoints.py feat(claude_code_gateway): issue rotating refresh tokens and a revocation endpoint (#44635) 2026-10-06 20:57:50 -07:00
test_skills_endpoints.py test(proxy): move utils, agent_endpoints and endpoint tests into tests/unit/proxy (#44006) 2026-10-01 11:06:42 -07:00
test_streaming_model_restamp.py test(proxy): move utils, agent_endpoints and endpoint tests into tests/unit/proxy (#44006) 2026-10-01 11:06:42 -07:00