Harden OAuth token handling#154
Conversation
|
Thanks a lot for putting this together @VykosMolt 🚀 This is a solid hardening pass, and the direction looks right to me. Hashing stored OAuth tokens, enforcing PKCE S256 for public clients, rejecting unsupported client auth methods, using a timing-safe PKCE comparison, and adding row locks around replay-sensitive grants all make sense. I think this is very close. Before merging, we have two requests:
One transition note: the legacy plaintext fallback is useful for compatibility, but existing plaintext refresh tokens can remain usable until expiry or rotation. I do not think we need to force a revoke migration in this PR unless we want the security benefit to land immediately, but it would be helpful to document the intended transition behavior in the PR description so the tradeoff is explicit. A small optional cleanup: _validate_pkce_request validates stripped PKCE values, but the original unstripped code_challenge and code_challenge_method are stored on the auth code. Storing the normalized values would keep authorize and token exchange behavior consistent. Not a security blocker, just a consistency improvement. One separate follow-up idea: the MCP endpoints still accept raw bearer tokens through the ?token= query param, which can leak through logs, browser history, or referrers. Since this is broader than the token-storage change and may exist for SSE compatibility, I am fine tracking that separately. Thanks again 🙏. This is good work and I think it is close to ready. 🤗 |
mbakgun
left a comment
There was a problem hiding this comment.
Thanks for the quick follow-up. I validated the latest PR head in a clean temporary checkout.
Looks good to merge. Thanks again.
Summary
This tightens the OAuth flow in a few places that came up during the audit:
token_endpoint_auth_methodvalues instead of silently treating them like public clientsVerification
SECRET_KEY=test-secret-key-that-is-long-enough-for-oauth-tests ENCRYPTION_KEY=0000000000000000000000000000000000000000000000000000000000000000 UV_CACHE_DIR=/tmp/heym-uv-cache uv run pytest tests/test_oauth_api.py tests/test_mcp_servers.py -qSECRET_KEY=test-secret-key-that-is-long-enough-for-oauth-tests ENCRYPTION_KEY=0000000000000000000000000000000000000000000000000000000000000000 UV_CACHE_DIR=/tmp/heym-uv-cache ./run_tests.sh