From 8ca4bb4787bf609e934f9b33c31d35dfa01480a2 Mon Sep 17 00:00:00 2001 From: Alex Leach Date: Sun, 12 Oct 2025 21:26:05 +0100 Subject: [PATCH] fix: Update ScopesSupported to match RFC 9728 Section 2 --- config.yaml | 5 ++-- internal/authz/default.go | 9 +++++- internal/authz/scope_validator.go | 7 +---- internal/config/config.go | 12 ++++---- internal/util/jwks.go | 50 ------------------------------- 5 files changed, 17 insertions(+), 66 deletions(-) diff --git a/config.yaml b/config.yaml index 47eb8eb..6322a81 100644 --- a/config.yaml +++ b/config.yaml @@ -53,9 +53,8 @@ protected_resource_metadata: resource_identifier: http://localhost:8080/sse audience: 2xGW_poFYoObUE_vUQxvGdPSUPwa scopes_supported: - - initialize: "mcp_init" - - tools/call: - - echo_tool: "mcp_echo_tool" + - "read:tools" + - "read:resources" authorization_servers: - https://api.asgardeo.io/t/openmcpauthdemo/oauth2/token jwks_uri: https://api.asgardeo.io/t/openmcpauthdemo/oauth2/jwks diff --git a/internal/authz/default.go b/internal/authz/default.go index 8b58fa0..4b23330 100644 --- a/internal/authz/default.go +++ b/internal/authz/default.go @@ -100,10 +100,17 @@ func (p *defaultProvider) ProtectedResourceMetadataHandler() http.HandlerFunc { w.Header().Set("Content-Type", "application/json") meta := map[string]interface{}{ "audience": p.cfg.ProtectedResourceMetadata.Audience, - "scopes_supported": p.cfg.ProtectedResourceMetadata.ScopesSupported, "authorization_servers": p.cfg.ProtectedResourceMetadata.AuthorizationServers, } + if len(p.cfg.ProtectedResourceMetadata.ScopesSupported) > 0 { + meta["scopes_supported"] = p.cfg.ProtectedResourceMetadata.ScopesSupported + } + + if p.cfg.ProtectedResourceMetadata.ResourceIdentifier != "" { + meta["resource"] = p.cfg.ProtectedResourceMetadata.ResourceIdentifier + } + if p.cfg.ProtectedResourceMetadata.JwksURI != "" { meta["jwks_uri"] = p.cfg.ProtectedResourceMetadata.JwksURI } diff --git a/internal/authz/scope_validator.go b/internal/authz/scope_validator.go index bf18a07..be8e337 100644 --- a/internal/authz/scope_validator.go +++ b/internal/authz/scope_validator.go @@ -7,7 +7,6 @@ import ( "github.com/golang-jwt/jwt/v4" "github.com/wso2/open-mcp-auth-proxy/internal/config" - "github.com/wso2/open-mcp-auth-proxy/internal/util" ) type ScopeValidator struct{} @@ -18,11 +17,7 @@ func (d *ScopeValidator) ValidateAccess( claims *jwt.MapClaims, config *config.Config, ) AccessControlResult { - env, err := util.ParseRPCRequest(r) - if err != nil { - return AccessControlResult{DecisionDeny, "bad JSON-RPC request"} - } - requiredScopes := util.GetRequiredScopes(config, env) + requiredScopes := config.ProtectedResourceMetadata.ScopesSupported if len(requiredScopes) == 0 { return AccessControlResult{DecisionAllow, ""} diff --git a/internal/config/config.go b/internal/config/config.go index 2a7958a..5d8095b 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -70,12 +70,12 @@ type ResponseConfig struct { } type ProtectedResourceMetadata struct { - ResourceIdentifier string `yaml:"resource_identifier"` - Audience string `yaml:"audience"` - ScopesSupported []map[string]interface{} `yaml:"scopes_supported"` - AuthorizationServers []string `yaml:"authorization_servers"` - JwksURI string `yaml:"jwks_uri,omitempty"` - BearerMethodsSupported []string `yaml:"bearer_methods_supported,omitempty"` + ResourceIdentifier string `yaml:"resource_identifier"` + Audience string `yaml:"audience"` + ScopesSupported []string `yaml:"scopes_supported"` + AuthorizationServers []string `yaml:"authorization_servers"` + JwksURI string `yaml:"jwks_uri,omitempty"` + BearerMethodsSupported []string `yaml:"bearer_methods_supported,omitempty"` } type PathConfig struct { diff --git a/internal/util/jwks.go b/internal/util/jwks.go index 1a00d6e..36a21dd 100644 --- a/internal/util/jwks.go +++ b/internal/util/jwks.go @@ -10,7 +10,6 @@ import ( "strings" "github.com/golang-jwt/jwt/v4" - "github.com/wso2/open-mcp-auth-proxy/internal/config" logger "github.com/wso2/open-mcp-auth-proxy/internal/logging" ) @@ -160,55 +159,6 @@ func ParseJWT(tokenStr string) (jwt.MapClaims, error) { return claims, nil } -// Process the required scopes -func GetRequiredScopes(cfg *config.Config, requestBody *RPCEnvelope) []string { - - var scopeObj interface{} - found := false - for _, m := range cfg.ProtectedResourceMetadata.ScopesSupported { - if val, ok := m[requestBody.Method]; ok { - scopeObj = val - found = true - break - } - } - if !found { - return nil - } - - switch v := scopeObj.(type) { - case string: - return []string{v} - case []any: - if requestBody.Params != nil { - if paramsMap, ok := requestBody.Params.(map[string]any); ok { - name, ok := paramsMap["name"].(string) - if ok { - for _, item := range v { - if scopeMap, ok := item.(map[interface{}]interface{}); ok { - if scopeVal, exists := scopeMap[name]; exists { - if scopeStr, ok := scopeVal.(string); ok { - return []string{scopeStr} - } - if scopeArr, ok := scopeVal.([]any); ok { - var scopes []string - for _, s := range scopeArr { - if str, ok := s.(string); ok { - scopes = append(scopes, str) - } - } - return scopes - } - } - } - } - } - } - } - } - - return nil -} // Extracts the Bearer token from the Authorization header func ExtractAccessToken(authHeader string) (string, error) {