feat!: add Private Key JWT (private_key_jwt) client authentication - #154
Merged
Conversation
Add private_key_jwt client authentication alongside the existing client secret. When a signing key is configured, the SDK signs a short-lived client assertion (RFC 7523) instead of sending a client secret. Client authentication is resolved in one place and applied uniformly across every token-endpoint call site. Also include the required response_type on Pushed Authorization Requests, which was previously missing and caused the request to be rejected.
kishore7snehil
marked this pull request as ready for review
August 12, 2026 13:45
nandan-bhat
reviewed
Aug 12, 2026
Address review feedback on private_key_jwt client authentication: - Route MFA challenge and verify through the client-auth resolver so private_key_jwt works for MFA step-up, not only client_secret. - Withhold the client secret from the OAuth client when a signing key is set, so the code exchange sends a single client authentication method. - Validate the signing key and algorithm at construction and raise ConfigurationError, instead of failing on the first token request. - Strip caller-supplied client-auth keys in the resolver so they cannot be injected through PAR or backchannel authorization params. - Document ConfigurationError on the interactive login entry points and the Private Key JWT limitations in the README.
Drive the login and MFA private_key_jwt tests through complete_interactive_login and the ServerClient-wired MFA client so a regression at the SDK call site fails the suite, not just the helper. Add the passkey signing-key caveat to examples/Passkeys.md, list the accepted signing algorithms in the README, document ConfigurationError on the MFA challenge and verify methods, and chain the client assertion validation error.
nandan-bhat
approved these changes
Aug 14, 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.
📋 Changes
This PR adds Private Key JWT (
private_key_jwt) client authentication to auth0-server-python, alongside the existing client secret. When a signing key is configured, the SDK authenticates to the token endpoint by signing a short-lived client assertion (RFC 7523) instead of sending a client secret. Client authentication is resolved in one place and applied uniformly across every client-authenticated call site.✨ Features
client_assertion_signing_keyandclient_assertion_signing_algoptions onServerClientselectprivate_key_jwt; when neither a signing key nor a client secret is configured, token requests raiseConfigurationErrorbefore any network callprivate_key_jwtis applied uniformly across all client-authenticated requests: authorization code exchange, refresh token, Custom Token Exchange, connection access token (Token Vault), backchannel (CIBA) initiate and grant, PAR, passkey signin, and MFA challenge and verifyclient_secret,client_assertion, andclient_assertion_typeare stripped from every client-authenticated request, so the SDK-controlled credentials cannot be overridden throughauthorization_params🔧 API Changes
ServerClientoptionclient_assertion_signing_key: Optional[str]- a PKCS8 PEM private key that enablesprivate_key_jwtServerClientoptionclient_assertion_signing_alg: Optional[str]- the assertion signing algorithm, defaulting toRS256build_client_assertion(private_key, client_id, issuer, alg)helper,validate_client_assertion_key(private_key, alg)helper, andCLIENT_ASSERTION_TYPEconstant inauth0_server_python.auth_schemes.client_assertionConfigurationError. The MFA challenge (/mfa/challenge) previously sentclient_secret: nullin the body for such a client, and now raisesConfigurationErrortoo. Configureclient_secretorclient_assertion_signing_key.response_typetocode. This was previously missing and caused the request to be rejected. A caller that set a differentresponse_typethroughauthorization_paramson the PAR path will have that value replaced withcode.📖 Documentation
README.md, covering the signing-key configuration, where to register the public key, the algorithm requirement, the passkey challenge limitation, and that private keys must not be committed to source control🧪 Testing
Contributor Checklist