Skip to content

security: verify JWT signature in OAuth2 base class (CWE-347) - #1632

Open
aryamirani wants to merge 1 commit into
diffgram:masterfrom
aryamirani:fix/jwt-signature-verification
Open

security: verify JWT signature in OAuth2 base class (CWE-347)#1632
aryamirani wants to merge 1 commit into
diffgram:masterfrom
aryamirani:fix/jwt-signature-verification

Conversation

@aryamirani

Copy link
Copy Markdown

Summary

The get_decoded_jwt_token() method in OAuth2ClientBase decodes JWT tokens with verify=False and options={"verify_signature": False}, allowing an attacker to forge tokens with arbitrary claims.

Security Impact

CWE-347: Improper Verification of Cryptographic Signature

This is a critical authentication bypass vulnerability. The unverified JWT decode is called from:

  • permissions.py:171get_user_from_oauth2() uses get_decoded_jwt_token() to extract the sub claim and look up the authenticated user
  • permissions.py:82,89,109id_token_has_expired() calls get_decoded_jwt_token() to check token expiry

An attacker can craft a JWT with an arbitrary sub claim (pointing to any user) and an exp claim far in the future. Since the signature is never verified, the application will accept the forged token and authenticate the attacker as any user.

Note: The KeycloakDiffgramClient.verify_token() already properly verifies JWT signatures using the provider's public key — this fix brings the same verification to the base class method used in the permissions flow.

Fix

When OAUTH2_PROVIDER_PUBLIC_KEY is configured:

  • Verify the JWT signature using the provider's RSA public key
  • Return an empty dict on verification failure (safe default)

When no public key is configured:

  • Log a clear security warning to alert operators
  • Fall back to unverified decode (preserves backward compatibility)

Also removes the deprecated verify parameter (replaced by options dict in PyJWT >= 2.0).

Testing

  • Existing JWT decode behavior is preserved when public key is configured
  • Invalid/forged tokens now correctly fail verification
  • Backward compatible with deployments that haven't configured the public key yet (with warning)

The get_decoded_jwt_token() method in OAuth2ClientBase was decoding
JWT tokens with verify=False and verify_signature=False, allowing
an attacker to forge tokens with arbitrary claims (e.g. user identity
via the 'sub' claim).

This is a critical authentication bypass since the method is called
from permissions.py to authenticate users via get_user_from_oauth2().

Fix: When OAUTH2_PROVIDER_PUBLIC_KEY is configured, verify the JWT
signature using the provider's RSA public key before trusting claims.
When no key is configured, log a security warning to alert operators.

Also removes the deprecated 'verify' parameter (replaced by 'options'
in PyJWT >= 2.0).

CWE-347: Improper Verification of Cryptographic Signature
CVSS: High (authentication bypass)
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