Skip to content

flask: Add internal password sync endpoint + strip password hash from API responses (2/3 split of #73) - #75

Open
RudraBJoshi wants to merge 2 commits into
Open-Coding-Society:mainfrom
dhyantsoni:split/flask/f2-password-sync-and-hash-leak
Open

flask: Add internal password sync endpoint + strip password hash from API responses (2/3 split of #73)#75
RudraBJoshi wants to merge 2 commits into
Open-Coding-Society:mainfrom
dhyantsoni:split/flask/f2-password-sync-and-hash-leak

Conversation

@RudraBJoshi

Copy link
Copy Markdown

Splitting #73 into smaller, independently-reviewable PRs across spring/flask/pages. This one covers password database syncing, security for transfers of data between the two dbs, and a related hash-leak fix (kept together — the sync endpoint's auth check isn't meaningfully separable from the endpoint itself without landing an insecure intermediate state).

POST /api/internal/sync-password: updates a user's password by uid, called server-to-server by Spring after an OAuth-verified reset. Gated by a shared secret (INTERNAL_SYNC_KEY, compared with hmac.compare_digest for timing-safety), fails closed if unset.

Password hash no longer returned by the general user API: GET /api/user, the bulk user list, and the create/update/delete/guest-create responses were all including the PBKDF2 hash in the JSON body, to any logged-in user, not just admins. Admin-only backup/export endpoints are deliberately left alone since a restore needs the hash.

Original PR: #73

RudraBJoshi and others added 2 commits August 24, 2026 11:25
POST /api/internal/sync-password: updates a user's password by uid,
called server-to-server by the Spring backend after it completes an
OAuth + student ID verified password reset, so the same account's Flask
password doesn't drift out of sync with Spring's.

Gated by a shared secret (INTERNAL_SYNC_KEY, compared with
hmac.compare_digest for timing-safety) instead of user auth, since this
is never called from a browser -- there's no existing service-to-service
auth mechanism in this app to reuse, and reusing the admin-only
PUT /api/user route would have meant giving Spring real Flask admin
credentials. This endpoint can only ever change one user's password, and
is a closed no-op if INTERNAL_SYNC_KEY is unset.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
GET /api/user (any logged-in user, not just admins) and the other UserAPI
create/update/delete responses were including the PBKDF2 hash from
User.read() in the JSON body. Adds _without_password() and applies it at
every general-purpose response site; the admin-only backup/export endpoints
in data_export_import_api.py are left alone since they need the hash for
restore fidelity.
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