handleProtectedResourceMetadata returns RFC 9728 protected resource metadata. This tells clients which authorization server protects this resource. RFC 9728 §3.3 requires the `resource` value to match the resource the client is accessing. We support both: - GET /.well-known/oauth-protected-resource
(c *echo.Context)
| 101 | // The path-suffixed form lets the `/mcp` endpoint advertise metadata that |
| 102 | // strict clients validate against the resource URL they actually requested. |
| 103 | func (s *Service) handleProtectedResourceMetadata(c *echo.Context) error { |
| 104 | baseURL := s.getBaseURL(c) |
| 105 | |
| 106 | const wellKnownPrefix = "/.well-known/oauth-protected-resource" |
| 107 | resource := baseURL |
| 108 | if subPath := strings.TrimPrefix(c.Request().URL.Path, wellKnownPrefix); subPath != "" && subPath != "/" { |
| 109 | // Ensure leading slash and trim any trailing slash. |
| 110 | if !strings.HasPrefix(subPath, "/") { |
| 111 | subPath = "/" + subPath |
| 112 | } |
| 113 | resource = baseURL + strings.TrimRight(subPath, "/") |
| 114 | } |
| 115 | |
| 116 | metadata := &protectedResourceMetadata{ |
| 117 | Resource: resource, |
| 118 | AuthorizationServers: []string{baseURL}, |
| 119 | BearerMethodsSupported: []string{"header"}, |
| 120 | } |
| 121 | return c.JSON(http.StatusOK, metadata) |
| 122 | } |