Fix MCP OAuth discovery failing on relative URL installs
Summary
On relative URL installs (e.g. external_url 'https://example.com/gitlab'), the /.well-known/oauth-authorization-server metadata response is missing registration_endpoint. This breaks MCP clients that rely on RFC 7591 Dynamic Client Registration — they fail with:
Incompatible auth server: does not support dynamic client registrationRoot Cause
JwksController#provider uses request.path to check whether the current request matches OAUTH_PATHS:
if request.path.in?(OAUTH_PATHS)With a relative URL install, Rails sets SCRIPT_NAME=/gitlab and strips it from PATH_INFO. However, request.path returns SCRIPT_NAME + PATH_INFO, so the value is /gitlab/.well-known/oauth-authorization-server — which does not match the entries in OAUTH_PATHS (/.well-known/oauth-authorization-server).
As a result, registration_endpoint is never added to the OAuth metadata, and the method falls through to super (the Doorkeeper default which doesn't include it).
The same issue affects the provider_response method's MCP scope filtering on line 64.
Evidence
Tested on a GitLab 18.8.4-ee instance with external_url 'https://host/gitlab':
Before fix — request.path = /gitlab/.well-known/oauth-authorization-server:
// GET /gitlab/.well-known/oauth-authorization-server
// registration_endpoint is MISSING
{
"issuer": "https://host/gitlab",
"authorization_endpoint": "https://host/gitlab/oauth/authorize",
"token_endpoint": "https://host/gitlab/oauth/token"
}After fix — request.path_info = /.well-known/oauth-authorization-server:
// GET /gitlab/.well-known/oauth-authorization-server
{
"issuer": "https://host/gitlab",
"authorization_endpoint": "https://host/gitlab/oauth/authorize",
"token_endpoint": "https://host/gitlab/oauth/token",
"registration_endpoint": "https://host/gitlab/oauth/register"
}Non-relative URL installs are unaffected — when SCRIPT_NAME is empty, request.path and request.path_info return identical values:
# Non-relative URL install (SCRIPT_NAME = '')
request.path: /.well-known/oauth-authorization-server
request.path_info: /.well-known/oauth-authorization-server
→ Both match OAUTH_PATHS ✓
# Relative URL install (SCRIPT_NAME = '/gitlab')
request.path: /gitlab/.well-known/oauth-authorization-server → no match ✗
request.path_info: /.well-known/oauth-authorization-server → match ✓Fix
Replace request.path with request.path_info in two places in JwksController:
- Line 23: the
OAUTH_PATHSmembership check in#provider - Line 64: the
.end_with?('/api/v4/mcp')check in#provider_response
Testing
- Verified
registration_endpointappears in metadata on relative URL install - Verified MCP client (
mcp-remote) successfully performs dynamic client registration and reaches the OAuth authorize flow - Verified non-relative URL installs are unaffected (
request.path == request.path_infowhenSCRIPT_NAMEis empty)