Skip to content

fix: use absolute OAuth authorize URL and allow non-admin users to authorize#4000

Closed
ecthelion77 wants to merge 1 commit intoIBM:mainfrom
forterro:fix/oauth-authorize-url-and-button-upstream
Closed

fix: use absolute OAuth authorize URL and allow non-admin users to authorize#4000
ecthelion77 wants to merge 1 commit intoIBM:mainfrom
forterro:fix/oauth-authorize-url-and-button-upstream

Conversation

@ecthelion77
Copy link
Copy Markdown
Contributor

🐛 Bug-fix PR

📌 Summary

Two related OAuth UX fixes for multi-user deployments:

  1. Relative authorize URL in error messages: When a tool invocation fails due to a missing OAuth token, the ToolInvocationError message contains /oauth/authorize/{id} — a relative path that AI agents (VS Code Copilot, etc.) cannot use. Fixed to build an absolute URL using settings.app_domain + settings.app_root_path.

  2. Authorize button hidden for non-admin users: In gateways_partial.html, the "Authorize" button is gated behind can_modify (admin/owner). Since OAuth authorization is a per-user action (each user needs their own token), any authenticated user with gateway access should be able to authorize. "Fetch/Refresh Tools" remains admin-only.

Fixes #3998

🔁 Reproduction Steps

Bug 1:

  1. Configure a gateway with OAuth enabled
  2. As a non-admin user, call a tool on that gateway via MCP client
  3. Error: "Visit /oauth/authorize/xxx to complete OAuth flow" — relative path

Bug 2:

  1. As a non-admin team member, open Admin UI gateways list
  2. OAuth gateway the user has access to is visible
  3. No "Authorize" button — only admins see it

🐞 Root Cause

  1. tool_service.py: Uses hardcoded relative path /oauth/authorize/{id} in two ToolInvocationError messages (line ~3162 and ~4165)
  2. gateways_partial.html: {% if gateway.authType == 'oauth' and can_modify %} groups the Authorize button with admin-only actions

💡 Fix Description

  1. tool_service.py: Build authorize_url from settings.app_domain + settings.app_root_path + /oauth/authorize/{id}. Applied in both invoke_tool and stream_invoke_tool code paths.
  2. gateways_partial.html: Change condition to {% if gateway.authType == 'oauth' %} (no can_modify) for the Authorize button. The {% if can_modify %} block now starts after the Authorize button, before Fetch/Refresh Tools.

🧪 Verification

Check Command Status
Lint suite make lint ⚠️ Not run (no local dev env)
Unit tests make test ⚠️ Not run (no local dev env)
Coverage ≥ 80 % make coverage ⚠️ Not run (no local dev env)
Manual regression Tested in production Kubernetes (3+ weeks) — VS Code Copilot receives clickable absolute URLs, non-admin team members can authorize gateways

📐 MCP Compliance

  • Matches current MCP spec
  • No breaking change to MCP clients

✅ Checklist

  • Code formatted
  • No secrets/credentials committed
  • DCO Signed-off-by included

@jonpspri jonpspri added SHOULD P2: Important but not vital; high-value items that are not crucial for the immediate release bug Something isn't working labels Apr 9, 2026
@ecthelion77 ecthelion77 force-pushed the fix/oauth-authorize-url-and-button-upstream branch from b3efbb9 to 08d8e37 Compare April 13, 2026 10:25
@gcgoncalves gcgoncalves force-pushed the fix/oauth-authorize-url-and-button-upstream branch 2 times, most recently from d6bba8a to 8c17227 Compare April 13, 2026 12:26
Copy link
Copy Markdown
Collaborator

@gcgoncalves gcgoncalves left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tool test response for an authorised user:

Image

Tool test response for a non-authorised user:

Image

@ecthelion77
Copy link
Copy Markdown
Contributor Author

Suggested labels: python, security

@gcgoncalves gcgoncalves force-pushed the fix/oauth-authorize-url-and-button-upstream branch from 8c17227 to 51d0923 Compare April 14, 2026 08:42
@gcgoncalves gcgoncalves force-pushed the fix/oauth-authorize-url-and-button-upstream branch from 51d0923 to 6c53f77 Compare April 14, 2026 15:47
…thorize

Two related fixes for OAuth UX in multi-user deployments:

1. tool_service.py: Build absolute authorize URL using
   settings.app_domain + settings.app_root_path instead of a
   relative path. AI agents (VS Code Copilot, etc.) receive
   clickable URLs in ToolInvocationError messages. Applied in
   both invoke_tool and stream_invoke_tool code paths.

2. gateways_partial.html: Decouple the OAuth Authorize button
   from the can_modify permission check. OAuth authorization is
   a per-user action (each user gets their own token), so any
   authenticated user with gateway access should be able to
   authorize. Fetch/Refresh Tools remains gated behind can_modify.

Fixes IBM#3998

Signed-off-by: Olivier Gintrand <olivier.gintrand@forterro.com>
@gcgoncalves gcgoncalves force-pushed the fix/oauth-authorize-url-and-button-upstream branch from 6c53f77 to 1b7cefc Compare April 16, 2026 14:33
@ecthelion77
Copy link
Copy Markdown
Contributor Author

Closing — both changes in this PR are now covered elsewhere:

  1. Absolute OAuth authorize URL (tool_service.py): included in PR feat(api): comprehensive Virtual Meta-Server with 12 meta-tools #3978 (Virtual Meta-Server)
  2. Non-admin authorize button (gateways_partial.html): merged upstream via PR feat(ui): allow non-owner users to authorize on accessible OAuth gateways #3935

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working SHOULD P2: Important but not vital; high-value items that are not crucial for the immediate release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: OAuth authorize URL is relative in ToolInvocationError + Authorize button hidden for non-admin users

3 participants