fix: enhance OAuth callback handling for error responses and missing authorization code#2899
fix: enhance OAuth callback handling for error responses and missing authorization code#2899ankit-gajera-merck wants to merge 4 commits intoIBM:mainfrom
Conversation
crivetimihai
left a comment
There was a problem hiding this comment.
Thanks for this PR, @ankit-gajera-merck. The error handling follows RFC 6749 Section 4.1.2.1 correctly, and the Microsoft Entra v2 resource-parameter logic is well-thought-out. The test coverage is thorough. A couple of items:
XSS vector via root_path in error HTML
oauth_router.py:310,326: root_path from request.scope is injected into the <a href="{root_path}/admin#gateways"> tag without escaping. While root_path is typically set by the ASGI server (not user-controlled), a reverse proxy misconfiguration could inject malicious content. Apply escape() to root_path the same way you did for error and error_description.
_should_include_resource_parameter double-checks after caller already checks
In _create_authorization_url_with_pkce (line 1030): if self._should_include_resource_parameter(credentials, scopes) and resource: — the method already returns False when credentials.get("resource") is falsy, so the trailing and resource is redundant. Minor, but simplifying to just the method call would be cleaner.
Good: _is_microsoft_entra_v2_endpoint correctly normalizes case and checks both host and path. The omit_resource flag provides an escape hatch for non-Entra providers. Tests cover both the auto-detection and the explicit flag.
|
Thanks @crivetimihai, I have addressed both items in latest commit:
|
4228bc3 to
4219ea0
Compare
|
Hello, @ankit-gajera-merck . To proceed with this PR, you'll need to rebase it. When I attempted a rebase, I ran into several merge conflicts. I have pushed that rebase to the PR branch. All conflicts were in the same location: The conflictThree commits from the contributor's branch each touched the same
HEAD had already simplified the body from a redundant Resolution (applied consistently each time)# Before (various incoming versions had isinstance branching and/or `and resource`)
resource = credentials.get("resource")
if self._should_include_resource_parameter(credentials, scopes) and resource:
if isinstance(resource, list):
params["resource"] = resource
else:
params["resource"] = resource
# After (all three conflicts resolved to this)
resource = credentials.get("resource")
if self._should_include_resource_parameter(credentials, scopes):
params["resource"] = resource # urlencode with doseq=True handles listsRationale:
For commit |
|
I've added an e2e testing framework for Entra-ID and some linting fixes. Pending load test, we should be GTG. |
|
@ankit-gajera-merck I will need you to:
and force push it to correct sign-offs on your commits. |
jonpspri
left a comment
There was a problem hiding this comment.
Open Questions / Assumptions
- mcpgateway/services/oauth_manager.py:968 assumes Entra v2 host matching on login.microsoftonline.com; national cloud hosts are likely out of scope for
this change. - mcpgateway/routers/oauth_router.py:289 now surfaces provider error_description to users (escaped). This is safe from XSS, but still intentionally exposes
provider text to the UI.
Overall Assessment
- PR quality is good, changes are internally consistent, security posture improves, and performance impact is minimal.
- Recommended to merge, with only the non-blocking coverage caveat on Entra national cloud hostname variants.
…authorization code Signed-off-by: Ankit Gajera <ankit.gajera@merckgroup.com>
…ssary resource checks Signed-off-by: Ankit Gajera <ankit.gajera@merckgroup.com>
Add comprehensive end-to-end tests for Microsoft Entra ID SSO integration that validate group-based admin role assignment against real Azure infrastructure. Tests included (15 total): - Admin role assignment based on Entra ID group membership - Non-admin user handling - Dynamic role promotion on re-login - Case-insensitive group ID matching - Real ROPC token acquisition and validation - Multiple admin groups configuration - Admin role retention behavior (by design - see IBM#2331) - Token validation (expired, invalid audience/issuer) - Sync disabled behavior The tests are fully self-contained: they create test users and groups in Azure AD before tests and clean them up afterward. Also includes comprehensive documentation in docs/docs/testing/entra-id-e2e.md covering setup, configuration, and test scenarios. Relates to: IBM#2331 Signed-off-by: Jonathan Springer <jps@s390x.com>
Signed-off-by: Jonathan Springer <jps@s390x.com>
a0d170a to
796258f
Compare
Hi @jonpspri , I have rebased and pushed my commits with sign-off. |
🔗 Related Issue
Closes #2881
📝 Summary
This PR fixes Microsoft Entra ID v2 OAuth authorization failures (
AADSTS9010010) caused by sendingresourcetogether with v2scope, and fixes callback handling when providers return OAuth errors without an authorization code.Key changes:
resourcefor Entra v2 scope-based flows (https://login.microsoftonline.com/.../oauth2/v2.0/...).omit_resourcesupport inoauth_configto disableresourceinjection when needed./oauth/callbackto:erroranderror_descriptioncodeoptionalcodeAlso added/updated unit tests for both the Entra v2
resourcebehavior and callback error handling paths.🏷️ Type of Change
🧪 Verification
make lintmake testmake coverage✅ Checklist
make black isort pre-commit)📓 Notes (optional)
Targeted local verification executed:
uv run ruff check mcpgateway/services/oauth_manager.py mcpgateway/routers/oauth_router.py tests/unit/mcpgateway/services/test_oauth_manager.py tests/unit/mcpgateway/routers/test_oauth_router.py✅uv run pytest -q tests/unit/mcpgateway/services/test_oauth_manager.py tests/unit/mcpgateway/routers/test_oauth_router.py✅