Repository navigation
fix(auth): keep PATCH credentials body within server-accepted token keys - #43
Merged
Merged
Conversation
campus #650 (merged to weekly) made OAuthToken.to_resource() dual-emit the RFC 6749 `scope` string alongside `scopes`, but the PATCH /credentials endpoint validates the body via OAuthToken(**payload), which rejects the `scope` alias with 422 VALIDATION_FAILED. Strip the alias in Credentials.Provider.User.update() so token updates keep working across the campus #648 compat window. Also bumps campus-suite to weekly head 56ae7b9 (0.1.16) carrying the RFC 6749 token interface (#650, #654), and adds contract tests pinning the token-endpoint and credentials resource wire shapes and the PATCH validation contract. Fixes #40
This was referenced Sep 30, 2026
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.
Summary
Implements the migration for #40, now that campus #648 is implemented: PRs nyjc-computing/campus#650 + nyjc-computing/campus#654 merged to
weeklyon 2026-09-30 (verified — weekly head 56ae7b9 is exactly the #654 merge).What changed
56ae7b9(0.1.16) — delivers the RFC 6749-compliantOAuthTokeninterface to the client via the existingweeklybranch pin.Credentials.Provider.User.update()strips thescopestring alias from the PATCH body. Campus validates PATCH/credentialsbodies viaOAuthToken(**payload), which rejects thescopealias thatto_resource()now dual-emits with 422VALIDATION_FAILED— i.e. the model's ownto_resource()output was no longer PATCHable. The strip is lossless (scopescarries the same information;scopeis just" ".join(scopes)). Tracked upstream in PATCH /credentials token validation rejects OAuthToken.to_resource() output since #650 (scope alias → 422) campus#655.tests/unit/test_oauth_token_contract.py) pin the wire shapes taken from the campus weekly route code: token-endpoint RFC payload deserialization (access_token/token_type/expires_in/scope),token_typecase normalisation, legacy-record compat, nested credentials-token deserialization, and the PATCH-body validation contract.Audit (issue #40 action item 1)
Credentials.Provider.User.update()→token.to_resource()scopealias strippedauth.token()/_exchange_code_for_token()→OAuthToken.from_resource(resp.json())from_resourceaccepts RFC keys (#650)UserCredentials.from_resource(credentials GET/list)Campus.use_token()→token.access_tokenoauth.poll_for_token(raw dict)logins.update(expiry_seconds)LoginSessionmodel, notOAuthTokensessions.new()scopeslist body keyAuthSession; #648 scope flip is server-internal storageCredentials.Provider.User.new(scopes, expiry_seconds)stubNotImplementedErrorstub mirroring the server's current POST/credentialscontract; revisit at campus deprecationDev-deployment exercise (issue #40 action item 2)
No
CLIENT_ID/CLIENT_SECRETin this environment, so the authenticated exercise against the Railway dev deployment could not be run autonomously. Instead, the wire shapes were taken from the campus weekly route code (oauth.pydevice-grant response;credentials.pyupdate_credentialsvalidation) and pinned in offline contract tests; both dev deployments were confirmed reachable (401 on authenticated routes = alive and enforcing auth). Completing the checklist live is expected green given the tests + route code: runCredentials.Provider.User.update()andUserCredentialsdeserialization against dev with credentials.Test plan