Repository navigation
fix: re-acquire session tokens via the login-session token route (#117) - #118
Merged
Merged
Conversation
get_token() and _get_token_from_session() resolved the user's campus bearer through the credentials management routes, which campus#854 made operator-only — every downstream with_user_session() 403'd (campus#963). Campus ratified the fix in campus#964: POST /auth/v1/logins/<session_id>/ token, session-bound re-acquisition (invariant A10). - logins.token() adds the session-bound lane: one Basic-authenticated endpoint call; the server reuses a live grant token or rotates an expired one itself; the response carries no refresh token - _get_token_from_session() collapses from three operator-gated calls (credentials GET -> refresh grant -> credentials PATCH) to that one call, with no fallback to the credentials path; force_refresh / refresh_if_expired are gone — re-calling the endpoint is the refresh - the 401 hook re-calls the endpoint after revoke_session() (the route denies user principals outright) - get_token() delegates to the same lane Relock campus-suite to weekly@50e69c9 (includes campus#964) and adapt the #879 skew test to a pre-#879 model fixture instead of depending on an old install.
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.
Fixes #117 — brings the SDK in line with campus#963, resolved campus-side by campus#964 (
POST /auth/v1/logins/<session_id>/token, invariant A10, merged to weekly 2026-10-26).Problem
get_token()andCampus._get_token_from_session()resolved the user's campus bearer through the credentials management blueprint, which campus#854 made operator-only. Every downstream-appwith_user_session()/auth.get_token()therefore 403'd — campus#963's exact impact (campus-classroom enrollment bridge, broker release, Send-to-Classroom all failing while browser login worked).Change
The session-token path now uses the session-bound re-acquisition lane, per the rollout note on campus#963 — one endpoint call, no fallback to the credentials path:
logins.token()(new):POST /auth/v1/logins/{session_id}/token— note the canonical path has no trailing slash (route rule is/<session_id>/token, unlike the CRUD subresources; Route trailing slash compliance: Add trailing slashes to subresource ID paths #13's canonicalization doesn't apply). Auth is the client's Basic credentials plus the session id; user principals are denied outright by the route.Campus._get_token_from_session()collapses from three operator-gated calls (credentials GET → refresh grant → credentials PATCH) to that one call.force_refresh/refresh_if_expiredare gone: the server reuses a live grant token and rotates an expired one itself, so re-calling the endpoint is the refresh.revoke_session()— still required, since presenting the stale user bearer to the new route is a 403.AuthRoot.get_token()delegates to the same lane. Server-sideinvalid_grant(gone session, revoked grant, lapsed refresh chain) surfaces asAPIErrorwithoauth_error="invalid_grant"— the same re-login cue as the feat(auth): refresh grant + device-flow parity for public clients — retire campus-cli's last raw token calls #87 public-client refresh.campus-suiteto weekly@50e69c9 (includes campus#964). This also surfaced a latent skew test:test_model_without_user_field_falls_backasserted the installed campus-suite lacked the #879userfield, and its own message said it needed a pre-#879 fixture once that stopped being true — it now builds that fixture directly.The
Credentialsresource class stays (operator/management surface); the SDK just stops walking it for user sessions. Retrieval matrix after this (per campus#963): app-as-user → login-session token route; upstream tokens → broker; CLI → device flow; service-to-service → client_credentials; ops inspection → credentials blueprint.Tests
test_token_refresh.py: rewritten for the new lane — one endpoint call with the exact path, response parsing (incl. theuser_idecho surviving asprovider_fields), no-session raises without HTTP,invalid_grantmapping, and a_get_token_from_sessiondelegation test asserting zero calls to the credentials/refresh/PATCH legs. Public-clientauth.refresh(stored)tests untouched.test_unauthorized_refresh.py: hook assertions updated (re-acquisition carries no kwargs now).poetry run pyrightclean (CI parity:poetry run pytest+poetry run pyright).Rollout
Downstream consumers unblock against dev once this merges (dev auth already runs weekly with the route). Per the #956 relock pattern, campus-side can relock
campus-api-pythonto the merge commit afterwards; campus-classroom and otherwith_user_session()callers need no code changes.