auth: add OAuth 2.0 Protected Resource Metadata handler
This change adds support for RFC 9728 (OAuth 2.0 Protected Resource Metadata) by introducing a `ProtectedResourceMetadataHandler`. The handler includes built-in CORS support with `Access-Control-Allow-Origin: *` by default, as OAuth metadata is public information meant for client discovery. Documentation includes examples for using custom CORS policies with popular middleware libraries (github.com/rs/cors and github.com/jub0bs/cors). The implementation follows RFC 9728 §3.1 for OAuth 2.0 Authorization Server Metadata discovery, enabling clients to discover protected resource capabilities and authentication requirements.
This commit is contained in:
parent
18cd63599d
commit
d6d6edd6d4
1 changed files with 275 additions and 11 deletions
43
auth/auth.go
43
auth/auth.go
|
|
@ -6,11 +6,14 @@ package auth
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/modelcontextprotocol/go-sdk/oauthex"
|
||||
)
|
||||
|
||||
// TokenInfo holds information from a bearer token.
|
||||
|
|
@ -123,3 +126,43 @@ func verify(req *http.Request, verifier TokenVerifier, opts *RequireBearerTokenO
|
|||
}
|
||||
return tokenInfo, "", 0
|
||||
}
|
||||
|
||||
// ProtectedResourceMetadataHandler returns an http.Handler that serves OAuth 2.0
|
||||
// protected resource metadata (RFC 9728) with CORS support.
|
||||
//
|
||||
// This handler allows cross-origin requests from any origin (Access-Control-Allow-Origin: *)
|
||||
// because OAuth metadata is public information intended for client discovery (RFC 9728 §3.1).
|
||||
// The metadata contains only non-sensitive configuration data about authorization servers
|
||||
// and supported scopes.
|
||||
//
|
||||
// No validation of metadata fields is performed; ensure metadata accuracy at configuration time.
|
||||
//
|
||||
// For more sophisticated CORS policies or to restrict origins, wrap this handler with a
|
||||
// CORS middleware like github.com/rs/cors or github.com/jub0bs/cors.
|
||||
func ProtectedResourceMetadataHandler(metadata *oauthex.ProtectedResourceMetadata) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Set CORS headers for cross-origin client discovery.
|
||||
// OAuth metadata is public information, so allowing any origin is safe.
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
|
||||
|
||||
// Handle CORS preflight requests
|
||||
if r.Method == http.MethodOptions {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
|
||||
// Only GET allowed for metadata retrieval
|
||||
if r.Method != http.MethodGet {
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(metadata); err != nil {
|
||||
http.Error(w, "Failed to encode metadata", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue