mcp: add optional issuer validator for pre-registered client validation (SEP-2352) (#946)

Fixes #978
This commit is contained in:
Guglielmo Colombo 2026-05-29 14:46:34 +02:00 • committed by GitHub
commit dfb45f1e11
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 190 additions and 5 deletions

View file

@ -12,7 +12,8 @@ import (
"errors"
"fmt"
"net/http"
"strings"
"github.com/modelcontextprotocol/go-sdk/internal/authutil"
)
// AuthServerMeta represents the metadata for an OAuth 2.0 authorization server,
@ -153,8 +154,7 @@ func GetAuthServerMeta(ctx context.Context, metadataURL, issuer string, c *http.
}
return nil, fmt.Errorf("%v", err) // Do not expose error types.
}
if strings.TrimRight(asm.Issuer, "/") != strings.TrimRight(issuer, "/") {
// Validate the Issuer field (see RFC 8414, section 3.3).
if !authutil.IssuersEqual(asm.Issuer, issuer) {
return nil, fmt.Errorf("metadata issuer %q does not match issuer URL %q", asm.Issuer, issuer)
}

View file

@ -18,6 +18,15 @@ type ClientCredentials struct {
// This is the most common authentication method for confidential clients.
// OPTIONAL. If not provided, the client is treated as a public client.
ClientSecretAuth *ClientSecretAuth
// Issuer is the issuer identifier of the authorization server these
// credentials are registered with. Pre-registered credentials are bound
// to a specific authorization server; when set, an error is returned if
// the discovered authorization server does not match, per SEP-2352.
// The comparison ignores a single trailing slash, matching the
// tolerance applied during RFC 8414 Section 3.3 metadata validation.
// OPTIONAL.
Issuer string
}
// ClientSecretAuth holds client secret authentication credentials.

View file

@ -73,7 +73,7 @@ func TestClientCredentials_ValidateCoversAllAuthFields(t *testing.T) {
var pointerFields int
for i := range typ.NumField() {
f := typ.Field(i)
if f.Name == "ClientID" {
if f.Name == "ClientID" || f.Name == "Issuer" {
continue
}
if f.Type.Kind() != reflect.Ptr {