Repository navigation
feature: auth and auth-oauthlib support for OAuth Demonstrable Proof-of-Presence (DPoP) #18800 - #18808
feature: auth and auth-oauthlib support for OAuth Demonstrable Proof-of-Presence (DPoP) #18800#18808jay0lee wants to merge 1 commit into
Conversation
Add Demonstrating Proof-of-Possession (DPoP) support per RFC 9449, binding OAuth 2.0 tokens to a cryptographic key so that stolen refresh tokens cannot be used without the corresponding private key. New modules: - google.auth.dpop: DPoPSigner ABC, SoftwareDPoPSigner for software-held keys (ES256, ES384, RS256), JWK thumbprint computation, DPoP proof creation, and helper utilities. - google.oauth2.dpop_credentials: DPoPCredentials subclass of Credentials that attaches DPoP proofs to token refresh requests, handles use_dpop_nonce challenges, and supports RAPT/reauth. Modifications to existing modules: - google.oauth2.credentials: extract _call_refresh_grant() hook so DPoPCredentials can override the refresh grant without duplicating the full refresh flow. - google.oauth2._client: add return_response_headers parameter to _token_endpoint_request_no_throw() so DPoP can capture DPoP-Nonce response headers. Google's authorization server validates DPoP proofs during token refresh and code exchange. Google resource servers currently accept only the Bearer authorization scheme; the DPoP proof header is included for RFC 9449 compliance and forward compatibility. Tests: 64 in test_dpop.py, 40 in test_dpop_credentials.py.
There was a problem hiding this comment.
Code Review
This pull request introduces Demonstrating Proof-of-Possession (DPoP) support per RFC 9449 across both google-auth and google-auth-oauthlib. It adds the DPoPSigner interface and SoftwareDPoPSigner implementation, a new DPoPCredentials class for binding tokens to cryptographic keys, and updates the OAuth flow and helper functions to handle DPoP parameters, proofs, and nonce challenges. Feedback on the changes highlights a bug in flow.py where the DPoP nonce is retrieved from the wrong object, a potential side-effect from modifying headers in-place, and a docstring mismatch in _client.py that could lead to a runtime unpacking error.
84a86e5 to
333b6f6
Compare
|
Tests failed because I was attempting one PR for both the I've rewritten the PR to focus on |
This PR implements OAuth DPoP (RFC, Google launch).
Because DPoP touches on and changes many parts of the traditional OAuth dance and, to avoid changing the behavior of our existing
Credentialsclass when DPoP is not in use, this implementation is it's own subclass,DPoPCredentials.See #18800 for more details.