From da3535b6786149733cd8383f9ffb41191f45a9a6 Mon Sep 17 00:00:00 2001 From: Jon <38672162+gainsley@users.noreply.github.com> Date: Thu, 14 May 2026 00:26:57 -0700 Subject: [PATCH] Compare auth server metadata issuer ignoring trailing slash (#955) oauthex/auth_meta.go: fixes metadata issuer comparison to ignore trailing slash difference Google's gmail MCP server returns `https://accounts.google.com/` as the Authorization Server in the Protected Resource Metadata, but returns `https://accounts.google.com` in the Auth Server Metadata. This causes a comparison failure per rfc8414 section-3.3: Authorization Server Metadata Validation. The authorization server URL is meant to be a base to build other URLs from, it does not seem necessary to enforce that the trailing slash (or lack thereof) matches with the issuer URL. Please see #953 for more details. Fixes #953 --------- Co-authored-by: Guglielmo Colombo --- oauthex/auth_meta.go | 3 ++- oauthex/auth_meta_test.go | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/oauthex/auth_meta.go b/oauthex/auth_meta.go index df1a0aa..255aca9 100644 --- a/oauthex/auth_meta.go +++ b/oauthex/auth_meta.go @@ -12,6 +12,7 @@ import ( "errors" "fmt" "net/http" + "strings" ) // AuthServerMeta represents the metadata for an OAuth 2.0 authorization server, @@ -145,7 +146,7 @@ func GetAuthServerMeta(ctx context.Context, metadataURL, issuer string, c *http. } return nil, fmt.Errorf("%v", err) // Do not expose error types. } - if asm.Issuer != issuer { + if strings.TrimRight(asm.Issuer, "/") != strings.TrimRight(issuer, "/") { // Validate the Issuer field (see RFC 8414, section 3.3). return nil, fmt.Errorf("metadata issuer %q does not match issuer URL %q", asm.Issuer, issuer) } diff --git a/oauthex/auth_meta_test.go b/oauthex/auth_meta_test.go index f390676..5c6c4ad 100644 --- a/oauthex/auth_meta_test.go +++ b/oauthex/auth_meta_test.go @@ -35,9 +35,10 @@ func TestAuthMetaParse(t *testing.T) { func TestGetAuthServerMetaPKCESupport(t *testing.T) { ctx := context.Background() tests := []struct { - name string - hasPKCESupport bool - wantError string + name string + hasPKCESupport bool + wantError string + issuerWithTrailingSlash bool }{ { name: "server_with_pkce_support", @@ -48,6 +49,12 @@ func TestGetAuthServerMetaPKCESupport(t *testing.T) { hasPKCESupport: false, wantError: "does not implement PKCE", }, + { + // ProtectedResourceMetadata may contain AuthorizationServers with a trailing slash (see Issue #953) + name: "issuer_with_trailing_slash", + hasPKCESupport: true, + issuerWithTrailingSlash: true, + }, } for _, tt := range tests { @@ -85,6 +92,9 @@ func TestGetAuthServerMetaPKCESupport(t *testing.T) { u, _ := url.Parse(ts.URL) issuer := "https://localhost:" + u.Port() metadataURL := issuer + "/.well-known/oauth-authorization-server" + if tt.issuerWithTrailingSlash { + issuer += "/" + } // The fake server presents a cert for example.com; set ServerName accordingly. httpClient := ts.Client()