Skip to content

feat(auth): renew expired tokens via Firebase refresh token#3

Open
dcaslin wants to merge 1 commit into
Alex-Keyes:mainfrom
dcaslin:feat/auto-refresh-token
Open

feat(auth): renew expired tokens via Firebase refresh token#3
dcaslin wants to merge 1 commit into
Alex-Keyes:mainfrom
dcaslin:feat/auto-refresh-token

Conversation

@dcaslin

@dcaslin dcaslin commented Jun 13, 2026

Copy link
Copy Markdown

Summary

Wires the MCP server up to the refresh-token support added in
boostcamp-api PR #2 (Alex-Keyes/boostcamp-api#2), so an expired Firebase ID
token is renewed automatically instead of failing the call and forcing a manual
uv run login.

The key fix: get_api_client() previously built BoostcampAPI(token=...) from
.env and never loaded the session, so the client had no refresh token and
couldn't renew. It now loads the saved session.

Changes

  • get_api_client() loads .boostcamp/session.pickle via load_session()
    — the updated library writes it as {token, refresh_token}. With the refresh
    token in hand, the library exchanges it at the Firebase secure-token endpoint
    on a 403 and retries. Falls back to the legacy BOOSTCAMP_AUTH_TOKEN from
    .env (token-only, no renewal) for logins that predate this support, and
    tolerates a corrupt/old-format pickle.
  • Dependency repointed to dcaslin/boostcamp-api@fix/firebase-refresh-token
    (the PR branch). A TODO in pyproject.toml and the checklist below track
    moving it back to upstream main once the API PR merges.
  • README session-management section updated: refresh token (not the
    password) is persisted, tokens auto-renew, and existing users run
    uv run login once to populate the refresh token.

Test plan

  • uv sync resolves to the refresh-token branch; server imports cleanly.
  • get_api_client() loads the session and a live get_my_profile() call
    succeeds against the real API.
  • Verified the loaded client exposes the refresh machinery
    (_refresh_token, _refresh_session).
  • After uv run login, verified end-to-end against real Firebase: the
    session pickle now holds {token, refresh_token} (no password/email),
    _refresh_session() exchanges the refresh token and the ID token
    actually changes, and a get_my_profile() call succeeds with the
    refreshed token.

Merge order

Note: independent of #2 (the training-history PR); both touch pyproject.toml
in different sections, so whichever merges second needs a trivial rebase.

🤖 Generated with Claude Code

Point boostcampapi at the refresh-token branch and load the saved session
(token + refresh token) instead of a bare env token, so the client renews an
expired Firebase ID token automatically on a 403 rather than failing the call
and forcing a manual re-login.

- get_api_client() now prefers load_session() from .boostcamp/session.pickle
  (which the updated library writes as {token, refresh_token}); falls back to
  the legacy BOOSTCAMP_AUTH_TOKEN from .env for older, token-only logins.
- Dependency pinned to dcaslin/boostcamp-api@fix/firebase-refresh-token until
  Alex-Keyes/boostcamp-api#2 merges, then repoint to
  upstream main.

Existing users must run `uv run login` once to populate the refresh token.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant