-
Notifications
You must be signed in to change notification settings - Fork 291
fix: asymmetric jwt encoding and decoding #973
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
3dfe943
to
0b85edc
Compare
This commit introduces the option to load private and public keys to use also support asymmetric jwt encoding and decoding Signed-off-by: Philip Miglinci <[email protected]>
Thanks! I'm reviewing / rebasing this PR, will push changes back. |
Signed-off-by: Mihai Criveti <[email protected]>
0b85edc
to
c73ac3f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JWT Asymmetric Algorithm Support
This PR adds comprehensive support for asymmetric JWT algorithms (RS256, RS384, RS512, etc.) while maintaining full backward compatibility with existing HMAC-based JWT functionality.
Key Changes
🔧 New Configuration Variables
JWT_PUBLIC_KEY_PATH
: Path to public key file for asymmetric algorithmsJWT_PRIVATE_KEY_PATH
: Path to private key file for asymmetric algorithmsJWT_AUDIENCE_VERIFICATION
: Toggle to disable JWT audience verification (useful for Dynamic Client Registration)
📁 New Files
mcpgateway/utils/jwt_config_helper.py
: JWT configuration validation and key management utilities
🔄 Modified Files
mcpgateway/config.py
: Added new JWT configuration settings with proper defaultsmcpgateway/utils/create_jwt_token.py
: Enhanced to support both symmetric and asymmetric algorithms with runtime key selectionmcpgateway/utils/verify_credentials.py
: Updated JWT verification to use configuration-based key selection- Multiple service files: Updated to use centralized JWT token creation
.env.example
: Enhanced with comprehensive JWT algorithm documentation and Makefile commandsREADME.md
: Updated authentication documentation table.gitignore
&.dockerignore
: Addedcerts/jwt/
directory for key storageMakefile
: Added JWT certificate generation targets with help documentationdocker-compose.yml
: Updated with JWT configuration options and instructions
🛠️ Infrastructure Improvements (Post-Review)
- Makefile Integration: Added
make certs-jwt
,make certs-jwt-ecdsa
,make certs-all
targets - Container Support: Added
make container-run-ssl-jwt
for full TLS + JWT asymmetric deployment - Path Standardization: Unified on
certs/jwt/
directory structure consistent with existing SSL certificate patterns - Idempotent Generation: Certificate targets won't overwrite existing keys, following existing
make certs
behavior
Features
✅ Algorithm Support
- HMAC Algorithms: HS256, HS384, HS512 (existing functionality preserved)
- RSA Algorithms: RS256, RS384, RS512 (new asymmetric support)
- ECDSA Algorithms: ES256, ES384, ES512 (supported via PyJWT)
✅ Security Features
- Configuration validation ensures required keys exist for chosen algorithm
- Prevents algorithm confusion attacks by consistently using configured algorithm
- Secure key file loading with proper error handling
- Audience verification can be disabled for DCR scenarios
✅ Backward Compatibility
- Existing HMAC JWT tokens continue to work unchanged
- All existing API endpoints maintain compatibility
- Default configuration remains HS256 with JWT_SECRET_KEY
Testing Results
✅ Unit Tests
- JWT creation tests: 10/10 passing
- JWT verification tests: 19/19 passing
- Full test coverage for new JWT configuration helper
✅ Integration Tests
- End-to-end asymmetric JWT functionality verified
- HMAC baseline functionality confirmed working
- Configuration validation tested with various scenarios
✅ Code Quality
- All linting checks passed (ruff, flake8, black)
- Documentation updated and reviewed
- Type hints and docstrings added for new functions
Usage Examples
HMAC (Current/Default)
JWT_ALGORITHM=HS256
JWT_SECRET_KEY=your-secret-key
RSA (New Asymmetric Support)
JWT_ALGORITHM=RS256
JWT_PUBLIC_KEY_PATH=certs/jwt/public.pem
JWT_PRIVATE_KEY_PATH=certs/jwt/private.pem
JWT_AUDIENCE_VERIFICATION=true
Generate RSA Keys
# Option 1: Use Makefile (Recommended - Integrated with existing certificate workflow)
make certs-jwt # Generates certs/jwt/{private,public}.pem with secure permissions
# Option 2: Manual generation
mkdir -p certs/jwt
openssl genrsa -out certs/jwt/private.pem 4096
openssl rsa -in certs/jwt/private.pem -pubout -out certs/jwt/public.pem
chmod 600 certs/jwt/private.pem
chmod 644 certs/jwt/public.pem
Generate ECDSA Keys (Alternative)
make certs-jwt-ecdsa # Generates certs/jwt/{ec_private,ec_public}.pem
Generate All Certificates
make certs-all # Generates both TLS certificates and JWT RSA keys
Migration Path
For Existing Deployments
No action required - existing HMAC configuration continues working unchanged.
For New Asymmetric Deployments
- Generate RSA key pair:
make certs-jwt
- Update environment variables:
- Set
JWT_ALGORITHM=RS256
- Set
JWT_PUBLIC_KEY_PATH=certs/jwt/public.pem
- Set
JWT_PRIVATE_KEY_PATH=certs/jwt/private.pem
- Set
- Restart application
Quick Production Setup
make certs-all # Generate both SSL and JWT certificates
make container-run-ssl-jwt # Run with full security stack
Benefits
🔒 Enhanced Security
- Support for asymmetric algorithms enables better key distribution
- Public key can be shared for token verification without exposing signing capability
- Better compliance with enterprise security requirements
🏗️ Architecture Flexibility
- Enables microservices architectures where multiple services verify tokens
- Supports federated authentication scenarios
- Compatible with standard JWT libraries and tools
🔄 Future-Proof
- Foundation for advanced features like key rotation
- Compatible with JWT standards and best practices
- Extensible for additional algorithms as needed
Risk Assessment
✅ Low Risk Changes
- Backward compatibility maintained
- Comprehensive testing completed
- Configuration validation prevents misconfigurations
- Graceful error handling for missing keys
⚠️ Considerations
- Key file management becomes part of deployment process for asymmetric setups
- Performance impact minimal (asymmetric operations are slightly slower than HMAC)
- Documentation updated to guide proper key generation and storage
Post-Review Enhancements
After the initial implementation review, significant infrastructure improvements were added:
🛠️ Makefile Integration
make certs-jwt
: Generate JWT RSA keys in./certs/jwt/
with secure permissions (600/644)make certs-jwt-ecdsa
: Generate JWT ECDSA keys with P-256 curve for high-performance scenariosmake certs-all
: Unified target to generate both SSL certificates and JWT keysmake container-run-ssl-jwt
: Complete production container with TLS + JWT asymmetric authentication- Idempotent behavior: Won't overwrite existing keys, consistent with existing
make certs
pattern
📁 Path Standardization
- Unified directory structure: JWT keys now use
certs/jwt/
instead ofjwt/
, consistent with SSL certificates - Volume mount efficiency: Single
./certs:/app/certs:ro
mount handles both SSL and JWT certificates - Secure permissions: Automatic 600 (private) and 644 (public) permission setting
🐳 Container & Docker Compose Integration
- docker-compose.yml: Updated with comprehensive JWT configuration examples
- Clear migration path: Commented configuration shows both HMAC (default) and RSA (production) options
- Volume mount documentation: Clear instructions for enabling asymmetric JWT with existing infrastructure
📚 Comprehensive Documentation Updates
- Architecture Decision Record (ADR-0004): Extended with asymmetric JWT algorithm support details
- Security Features Documentation: Enhanced JWT capabilities section with algorithm breakdown
- Configuration Reference: Complete JWT examples for HMAC, RSA, ECDSA, and DCR scenarios
- Security Guide: Production JWT security recommendations and key management best practices
- Kubernetes Deployment: Full production deployment examples with secret management and RBAC
- Enhanced .env.example: Self-documenting configuration with Makefile command references
⚡ Developer Experience Improvements
- One-command setup:
make certs-all && make container-run-ssl-jwt
for complete production stack - Consistent workflows: JWT certificate management follows same patterns as SSL certificates
- Clear documentation: Every configuration option includes generation commands and use cases
- Production ready: Kubernetes examples with proper secret management and security considerations
Ready for Merge
This PR has been thoroughly reviewed, tested, and enhanced:
- ✅ Code review completed with comprehensive functionality verification
- ✅ All tests passing (JWT creation: 10/10, JWT verification: 19/19)
- ✅ Complete documentation coverage across all relevant docs
- ✅ Linting issues resolved (ruff, flake8, black all passing)
- ✅ End-to-end functionality verified for both HMAC and asymmetric algorithms
- ✅ Backward compatibility confirmed with existing HMAC configurations
- ✅ Infrastructure integration complete with Makefile, Docker Compose, and container support
- ✅ Production deployment ready with Kubernetes examples and security best practices
The implementation follows security best practices, maintains the existing API contract, provides seamless infrastructure integration, and adds powerful new asymmetric JWT capabilities with comprehensive developer tooling.
Signed-off-by: Mihai Criveti <[email protected]>
🐛 Bug-fix PR
📌 Summary
This commit introduces the option to load private and public keys to use also support asymmetric jwt encoding and decoding
🔁 Reproduction Steps
Try to set the
JWT_ALGORITHM
to an asymmetric algo likeRS256
.🐞 Root Cause
Asymmetric signature creation and verification require public private keys.
Previously only
JWT_SECRET_KEY
was available, which was insufficient.💡 Fix Description
Introducing two new env variables
JWT_PUBLIC_KEY_PATH
andJWT_PRIVATE_KEY_PATH
in addition toJWT_AUDIENCE_VERIFICATION
which needs to be disabled for dynamic client registration.Additionally I refactored al jwt encoding and decoding operations to through a single method.
✅ Checklist
make black isort pre-commit
)