Skip to content

Commit bf94a06

Browse files
reyortiz3claude
andauthored
Fall through to well-known discovery when resource metadata auth fails (#4371)
When a server returns resource_metadata in its WWW-Authenticate header, Priority 3 (RFC 9728) would hard-return on any failure, preventing Priorities 4 and 5 from running. For servers like Sourcegraph and Deepsearch whose authorization_servers list contains path-based URLs (e.g. /.api/mcp/deepsearch), RFC 8414 tenant extraction generates /.well-known/oauth-authorization-server/.api/mcp/deepsearch — an endpoint those servers don't serve. Validation fails, Priority 3 errors, and auth is broken despite Priorities 4/5 being able to derive the correct root-domain issuer. Fix by capturing the error from tryDiscoverFromResourceMetadata and only returning on success; failures now log at DEBUG and fall through to well-known probing (Priority 4) and URL-derived issuer (Priority 5), restoring the behaviour that existed before 6cad0b5. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 6b8f044 commit bf94a06

2 files changed

Lines changed: 13 additions & 8 deletions

File tree

pkg/auth/remote/handler.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,11 @@ func (h *Handler) discoverIssuerAndScopes(
333333

334334
// Priority 3: Fetch from resource metadata (RFC 9728)
335335
if authInfo.ResourceMetadata != "" {
336-
return h.tryDiscoverFromResourceMetadata(ctx, authInfo.ResourceMetadata)
336+
issuer, scopes, authServerInfo, err := h.tryDiscoverFromResourceMetadata(ctx, authInfo.ResourceMetadata)
337+
if err == nil {
338+
return issuer, scopes, authServerInfo, nil
339+
}
340+
slog.Debug("Resource metadata discovery failed, falling through to well-known discovery", "error", err)
337341
}
338342

339343
// Priority 4: Try to discover actual issuer from the server's well-known endpoint

pkg/auth/remote/handler_test.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -169,15 +169,15 @@ func TestDiscoverIssuerAndScopes(t *testing.T) {
169169
expectError: false,
170170
},
171171
{
172-
name: "malformed resource metadata URL",
172+
name: "malformed resource metadata URL falls through to URL-derived issuer",
173173
config: &Config{},
174174
authInfo: &discovery.AuthInfo{
175175
Type: "OAuth",
176176
ResourceMetadata: "not-a-url",
177177
},
178-
remoteURL: "https://server.example.com",
179-
expectError: true,
180-
errorContains: "could not determine OAuth issuer",
178+
remoteURL: "https://server.example.com",
179+
expectError: false,
180+
expectedIssuer: "https://server.example.com",
181181
},
182182

183183
// Edge cases
@@ -442,10 +442,11 @@ func TestDiscoverIssuerAndScopes_Security(t *testing.T) {
442442
ctx, cancel := context.WithTimeout(t.Context(), 1*time.Second)
443443
defer cancel()
444444

445-
_, _, _, err := handler.discoverIssuerAndScopes(ctx, authInfo, "https://server.example.com")
445+
issuer, _, _, err := handler.discoverIssuerAndScopes(ctx, authInfo, "https://server.example.com")
446446

447-
// Should timeout or fail gracefully, not hang or crash
448-
assert.Error(t, err)
447+
// Should not hang or crash; Priority 3 fails gracefully and falls through to URL-derived issuer
448+
require.NoError(t, err)
449+
assert.Equal(t, "https://server.example.com", issuer)
449450
})
450451
}
451452

0 commit comments

Comments
 (0)