feat: add JWT claims extraction plugin (Issue #1439)-sweng5#2853
Conversation
e93a914 to
10fea73
Compare
|
Thanks @yiannis2804. Clean plugin implementation that follows the framework patterns. Code review observations:
|
b32a40e to
c6da888
Compare
Code Review Response@crivetimihai Thanks for the detailed review! All feedback has been addressed: 1. ✅ Security documentation (
|
Implements JWT claims and metadata extraction plugin for downstream authorization plugins (Cedar, OPA, etc.). Features: - Extracts standard JWT claims (sub, iss, aud, exp, iat, nbf, jti) - Extracts custom claims (roles, permissions, groups, attributes) - Supports RFC 9396 Rich Authorization Requests - Non-blocking permissive mode - Stores claims in global_context.metadata['jwt_claims'] Plugin hooks into HTTP_AUTH_RESOLVE_USER to extract claims after JWT verification and makes them available to policy enforcement plugins. Implementation: - Uses PluginContext correctly to access global_context - Proper hook method naming (http_auth_resolve_user) - Returns continue_processing=True for passthrough behavior - Error handling with graceful fallback Includes: - Plugin implementation with error handling - Configuration file (YAML) - Comprehensive test suite (5 tests, all passing) - Documentation with usage examples for Cedar/OPA Testing: - All 5 plugin tests passing - Linting clean (ruff + flake8) - Coverage: 90% Related to: - Issue IBM#1439: JWT claims and metadata extraction plugin - Issue IBM#1422: [EPIC] Agent and tool authentication and authorization - RFC 9396: Rich Authorization Requests Signed-off-by: yiannis2804 <yiannis2804@gmail.com>
Addressed all 5 review comments from @[reviewer-name]:
1. Security documentation (verify_signature=False):
- Added prominent SECURITY NOTE in module docstring
- Added Security Considerations section to README
- Documented token pre-verification assumption and risks
2. Logging sensitivity (PII leak prevention):
- Changed logger.info() to logger.debug() for claim extraction
- Only log claim count, not claim contents
- Prevents sensitive data exposure in production logs
3. Safer header access pattern:
- Replaced hasattr() with getattr(payload.headers, 'root', {})
- More robust against header model changes
- Fails gracefully with empty dict default
4. Copyright year correction:
- Updated from 2025 to 2026 in all files
5. Coverage badge deletion:
- File is auto-generated (in .gitignore)
- Not present in upstream/main
- Correctly excluded from version control
All tests passing (5/5), linting clean, ready for review.
Related to: IBM#1439
Signed-off-by: yiannis2804 <yiannis2804@gmail.com>
- Move plugin from mcpgateway/plugins/ to plugins/ (correct location) - Rename plugin.py to jwt_claims_extraction.py, config.yaml to plugin-manifest.yaml (match naming conventions) - Fix critical security doc: http_auth_resolve_user fires BEFORE JWT verification, not after — document the actual security model - Write to global_context.state instead of metadata (metadata is read-only from plugin perspective per framework docs) - Add Pydantic config model (JwtClaimsExtractionConfig) with configurable context_key - Add __init__ constructor calling super().__init__(config) - Add from __future__ import annotations - Add Bearer scheme validation in _extract_token - Use lazy logging format strings instead of f-strings - Remove unnecessary hasattr check on metadata - Remove error string leak from result metadata - Fix copyright year consistency (2026 across all files) - Fix SPDX-License-Identifier: Apache-2.0 headers - Revert unnecessary MANIFEST.in additions - Move tests to tests/unit/plugins/ and add new test cases for non-Bearer scheme rejection and custom context_key config Closes IBM#1439 Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
c6da888 to
838946d
Compare
|
Hi @yiannis2804 — thanks for this contribution! The JWT claims extraction plugin is a great idea and fills an important gap for downstream authorization (Cedar, OPA, etc.). I've rebased your branch onto Key fixesSecurity documentation — The original docstring stated that tokens are pre-verified before
Was missing: The plugin wasn't registered in plugins/config.yaml — without that entry it would never load at runtime. Added it as mode: "disabled" (users opt in by changing to "permissive") Consistency with codebase conventions
Test improvements
Please review the changes and let me know if you have any questions. |
Adds disabled-by-default registration entry so the plugin can be activated by setting mode to "permissive". Closes IBM#1439 Signed-off-by: Mihai Criveti <crivetimihai@gmail.com>
* feat: add JWT claims extraction plugin (Issue #1439) Implements JWT claims and metadata extraction plugin for downstream authorization plugins (Cedar, OPA, etc.). Features: - Extracts standard JWT claims (sub, iss, aud, exp, iat, nbf, jti) - Extracts custom claims (roles, permissions, groups, attributes) - Supports RFC 9396 Rich Authorization Requests - Non-blocking permissive mode - Stores claims in global_context.metadata['jwt_claims'] Plugin hooks into HTTP_AUTH_RESOLVE_USER to extract claims after JWT verification and makes them available to policy enforcement plugins. Implementation: - Uses PluginContext correctly to access global_context - Proper hook method naming (http_auth_resolve_user) - Returns continue_processing=True for passthrough behavior - Error handling with graceful fallback Includes: - Plugin implementation with error handling - Configuration file (YAML) - Comprehensive test suite (5 tests, all passing) - Documentation with usage examples for Cedar/OPA Testing: - All 5 plugin tests passing - Linting clean (ruff + flake8) - Coverage: 90% Related to: - Issue #1439: JWT claims and metadata extraction plugin - Issue #1422: [EPIC] Agent and tool authentication and authorization - RFC 9396: Rich Authorization Requests Signed-off-by: yiannis2804 <yiannis2804@gmail.com> * fix: address PR code review feedback Addressed all 5 review comments from @[reviewer-name]: 1. Security documentation (verify_signature=False): - Added prominent SECURITY NOTE in module docstring - Added Security Considerations section to README - Documented token pre-verification assumption and risks 2. Logging sensitivity (PII leak prevention): - Changed logger.info() to logger.debug() for claim extraction - Only log claim count, not claim contents - Prevents sensitive data exposure in production logs 3. Safer header access pattern: - Replaced hasattr() with getattr(payload.headers, 'root', {}) - More robust against header model changes - Fails gracefully with empty dict default 4. Copyright year correction: - Updated from 2025 to 2026 in all files 5. Coverage badge deletion: - File is auto-generated (in .gitignore) - Not present in upstream/main - Correctly excluded from version control All tests passing (5/5), linting clean, ready for review. Related to: #1439 Signed-off-by: yiannis2804 <yiannis2804@gmail.com> * fix: align JWT claims extraction plugin with framework conventions - Move plugin from mcpgateway/plugins/ to plugins/ (correct location) - Rename plugin.py to jwt_claims_extraction.py, config.yaml to plugin-manifest.yaml (match naming conventions) - Fix critical security doc: http_auth_resolve_user fires BEFORE JWT verification, not after — document the actual security model - Write to global_context.state instead of metadata (metadata is read-only from plugin perspective per framework docs) - Add Pydantic config model (JwtClaimsExtractionConfig) with configurable context_key - Add __init__ constructor calling super().__init__(config) - Add from __future__ import annotations - Add Bearer scheme validation in _extract_token - Use lazy logging format strings instead of f-strings - Remove unnecessary hasattr check on metadata - Remove error string leak from result metadata - Fix copyright year consistency (2026 across all files) - Fix SPDX-License-Identifier: Apache-2.0 headers - Revert unnecessary MANIFEST.in additions - Move tests to tests/unit/plugins/ and add new test cases for non-Bearer scheme rejection and custom context_key config Closes #1439 Signed-off-by: Mihai Criveti <crivetimihai@gmail.com> * fix: register JWT claims extraction plugin in config.yaml Adds disabled-by-default registration entry so the plugin can be activated by setting mode to "permissive". Closes #1439 Signed-off-by: Mihai Criveti <crivetimihai@gmail.com> --------- Signed-off-by: yiannis2804 <yiannis2804@gmail.com> Signed-off-by: Mihai Criveti <crivetimihai@gmail.com> Co-authored-by: Mihai Criveti <crivetimihai@gmail.com>
* feat: add JWT claims extraction plugin (Issue #1439) Implements JWT claims and metadata extraction plugin for downstream authorization plugins (Cedar, OPA, etc.). Features: - Extracts standard JWT claims (sub, iss, aud, exp, iat, nbf, jti) - Extracts custom claims (roles, permissions, groups, attributes) - Supports RFC 9396 Rich Authorization Requests - Non-blocking permissive mode - Stores claims in global_context.metadata['jwt_claims'] Plugin hooks into HTTP_AUTH_RESOLVE_USER to extract claims after JWT verification and makes them available to policy enforcement plugins. Implementation: - Uses PluginContext correctly to access global_context - Proper hook method naming (http_auth_resolve_user) - Returns continue_processing=True for passthrough behavior - Error handling with graceful fallback Includes: - Plugin implementation with error handling - Configuration file (YAML) - Comprehensive test suite (5 tests, all passing) - Documentation with usage examples for Cedar/OPA Testing: - All 5 plugin tests passing - Linting clean (ruff + flake8) - Coverage: 90% Related to: - Issue #1439: JWT claims and metadata extraction plugin - Issue #1422: [EPIC] Agent and tool authentication and authorization - RFC 9396: Rich Authorization Requests Signed-off-by: yiannis2804 <yiannis2804@gmail.com> * fix: address PR code review feedback Addressed all 5 review comments from @[reviewer-name]: 1. Security documentation (verify_signature=False): - Added prominent SECURITY NOTE in module docstring - Added Security Considerations section to README - Documented token pre-verification assumption and risks 2. Logging sensitivity (PII leak prevention): - Changed logger.info() to logger.debug() for claim extraction - Only log claim count, not claim contents - Prevents sensitive data exposure in production logs 3. Safer header access pattern: - Replaced hasattr() with getattr(payload.headers, 'root', {}) - More robust against header model changes - Fails gracefully with empty dict default 4. Copyright year correction: - Updated from 2025 to 2026 in all files 5. Coverage badge deletion: - File is auto-generated (in .gitignore) - Not present in upstream/main - Correctly excluded from version control All tests passing (5/5), linting clean, ready for review. Related to: #1439 Signed-off-by: yiannis2804 <yiannis2804@gmail.com> * fix: align JWT claims extraction plugin with framework conventions - Move plugin from mcpgateway/plugins/ to plugins/ (correct location) - Rename plugin.py to jwt_claims_extraction.py, config.yaml to plugin-manifest.yaml (match naming conventions) - Fix critical security doc: http_auth_resolve_user fires BEFORE JWT verification, not after — document the actual security model - Write to global_context.state instead of metadata (metadata is read-only from plugin perspective per framework docs) - Add Pydantic config model (JwtClaimsExtractionConfig) with configurable context_key - Add __init__ constructor calling super().__init__(config) - Add from __future__ import annotations - Add Bearer scheme validation in _extract_token - Use lazy logging format strings instead of f-strings - Remove unnecessary hasattr check on metadata - Remove error string leak from result metadata - Fix copyright year consistency (2026 across all files) - Fix SPDX-License-Identifier: Apache-2.0 headers - Revert unnecessary MANIFEST.in additions - Move tests to tests/unit/plugins/ and add new test cases for non-Bearer scheme rejection and custom context_key config Closes #1439 Signed-off-by: Mihai Criveti <crivetimihai@gmail.com> * fix: register JWT claims extraction plugin in config.yaml Adds disabled-by-default registration entry so the plugin can be activated by setting mode to "permissive". Closes #1439 Signed-off-by: Mihai Criveti <crivetimihai@gmail.com> --------- Signed-off-by: yiannis2804 <yiannis2804@gmail.com> Signed-off-by: Mihai Criveti <crivetimihai@gmail.com> Co-authored-by: Mihai Criveti <crivetimihai@gmail.com> Signed-off-by: Vishu Bhatnagar <vishu.bhatnagar@ibm.com>
) * feat: add JWT claims extraction plugin (Issue IBM#1439) Implements JWT claims and metadata extraction plugin for downstream authorization plugins (Cedar, OPA, etc.). Features: - Extracts standard JWT claims (sub, iss, aud, exp, iat, nbf, jti) - Extracts custom claims (roles, permissions, groups, attributes) - Supports RFC 9396 Rich Authorization Requests - Non-blocking permissive mode - Stores claims in global_context.metadata['jwt_claims'] Plugin hooks into HTTP_AUTH_RESOLVE_USER to extract claims after JWT verification and makes them available to policy enforcement plugins. Implementation: - Uses PluginContext correctly to access global_context - Proper hook method naming (http_auth_resolve_user) - Returns continue_processing=True for passthrough behavior - Error handling with graceful fallback Includes: - Plugin implementation with error handling - Configuration file (YAML) - Comprehensive test suite (5 tests, all passing) - Documentation with usage examples for Cedar/OPA Testing: - All 5 plugin tests passing - Linting clean (ruff + flake8) - Coverage: 90% Related to: - Issue IBM#1439: JWT claims and metadata extraction plugin - Issue IBM#1422: [EPIC] Agent and tool authentication and authorization - RFC 9396: Rich Authorization Requests Signed-off-by: yiannis2804 <yiannis2804@gmail.com> * fix: address PR code review feedback Addressed all 5 review comments from @[reviewer-name]: 1. Security documentation (verify_signature=False): - Added prominent SECURITY NOTE in module docstring - Added Security Considerations section to README - Documented token pre-verification assumption and risks 2. Logging sensitivity (PII leak prevention): - Changed logger.info() to logger.debug() for claim extraction - Only log claim count, not claim contents - Prevents sensitive data exposure in production logs 3. Safer header access pattern: - Replaced hasattr() with getattr(payload.headers, 'root', {}) - More robust against header model changes - Fails gracefully with empty dict default 4. Copyright year correction: - Updated from 2025 to 2026 in all files 5. Coverage badge deletion: - File is auto-generated (in .gitignore) - Not present in upstream/main - Correctly excluded from version control All tests passing (5/5), linting clean, ready for review. Related to: IBM#1439 Signed-off-by: yiannis2804 <yiannis2804@gmail.com> * fix: align JWT claims extraction plugin with framework conventions - Move plugin from mcpgateway/plugins/ to plugins/ (correct location) - Rename plugin.py to jwt_claims_extraction.py, config.yaml to plugin-manifest.yaml (match naming conventions) - Fix critical security doc: http_auth_resolve_user fires BEFORE JWT verification, not after — document the actual security model - Write to global_context.state instead of metadata (metadata is read-only from plugin perspective per framework docs) - Add Pydantic config model (JwtClaimsExtractionConfig) with configurable context_key - Add __init__ constructor calling super().__init__(config) - Add from __future__ import annotations - Add Bearer scheme validation in _extract_token - Use lazy logging format strings instead of f-strings - Remove unnecessary hasattr check on metadata - Remove error string leak from result metadata - Fix copyright year consistency (2026 across all files) - Fix SPDX-License-Identifier: Apache-2.0 headers - Revert unnecessary MANIFEST.in additions - Move tests to tests/unit/plugins/ and add new test cases for non-Bearer scheme rejection and custom context_key config Closes IBM#1439 Signed-off-by: Mihai Criveti <crivetimihai@gmail.com> * fix: register JWT claims extraction plugin in config.yaml Adds disabled-by-default registration entry so the plugin can be activated by setting mode to "permissive". Closes IBM#1439 Signed-off-by: Mihai Criveti <crivetimihai@gmail.com> --------- Signed-off-by: yiannis2804 <yiannis2804@gmail.com> Signed-off-by: Mihai Criveti <crivetimihai@gmail.com> Co-authored-by: Mihai Criveti <crivetimihai@gmail.com>
🔗 Related Issue
Closes #1439
TCD SwEng Group 5
📝 Summary
Implements JWT claims and metadata extraction plugin for downstream authorization plugins (Cedar, OPA, etc.).
Extracts standard and custom JWT claims after verification and stores them in
global_context.metadata["jwt_claims"]for use by policy enforcement plugins.🏷️ Type of Change
🧪 Verification
make lintmake testmake coverage✅ Checklist
make black isort pre-commit)📓 Notes
Features:
Implementation:
HTTP_AUTH_RESOLVE_USERPluginContextcorrectly to accessglobal_contextcontinue_processing=Truefor passthrough behaviorRelated: