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
|
|
@ -20,6 +20,7 @@ import (
|
|||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/modelcontextprotocol/go-sdk/auth"
|
||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
"github.com/modelcontextprotocol/go-sdk/oauthex"
|
||||
)
|
||||
|
||||
// This example demonstrates how to integrate auth.RequireBearerToken middleware
|
||||
|
|
@ -237,7 +238,8 @@ func main() {
|
|||
|
||||
// Create authentication middleware.
|
||||
jwtAuth := auth.RequireBearerToken(verifyJWT, &auth.RequireBearerTokenOptions{
|
||||
Scopes: []string{"read"}, // Require "read" permission
|
||||
Scopes: []string{"read"}, // Require "read" permission
|
||||
ResourceMetadataURL: "http://localhost:8080/.well-known/oauth-protected-resource",
|
||||
})
|
||||
|
||||
apiKeyAuth := auth.RequireBearerToken(verifyAPIKey, &auth.RequireBearerTokenOptions{
|
||||
|
|
@ -340,22 +342,36 @@ func main() {
|
|||
})
|
||||
})
|
||||
|
||||
// OAuth protected resource metadata endpoint.
|
||||
// This endpoint provides OAuth configuration information to clients.
|
||||
// CORS is enabled by default to support cross-origin client discovery.
|
||||
metadata := &oauthex.ProtectedResourceMetadata{
|
||||
Resource: "http://localhost:8080/mcp/jwt",
|
||||
AuthorizationServers: []string{
|
||||
"https://auth.example.com/.well-known/openid-configuration",
|
||||
},
|
||||
ScopesSupported: []string{"read", "write"},
|
||||
}
|
||||
http.Handle("/.well-known/oauth-protected-resource",
|
||||
auth.ProtectedResourceMetadataHandler(metadata))
|
||||
|
||||
// Start the HTTP server.
|
||||
log.Println("Authenticated MCP Server")
|
||||
log.Println("========================")
|
||||
log.Println("Server starting on", *httpAddr)
|
||||
log.Println()
|
||||
log.Println("Available endpoints:")
|
||||
log.Println(" GET /health - Health check (no auth)")
|
||||
log.Println(" GET /generate-token - Generate JWT token")
|
||||
log.Println(" POST /generate-api-key - Generate API key")
|
||||
log.Println(" POST /mcp/jwt - MCP endpoint (JWT auth)")
|
||||
log.Println(" POST /mcp/apikey - MCP endpoint (API key auth)")
|
||||
log.Println(" GET /health - Health check (no auth)")
|
||||
log.Println(" GET /.well-known/oauth-protected-resource - OAuth resource metadata")
|
||||
log.Println(" GET /generate-token - Generate JWT token")
|
||||
log.Println(" POST /generate-api-key - Generate API key")
|
||||
log.Println(" POST /mcp/jwt - MCP endpoint (JWT auth)")
|
||||
log.Println(" POST /mcp/apikey - MCP endpoint (API key auth)")
|
||||
log.Println()
|
||||
log.Println("Available MCP Tools:")
|
||||
log.Println(" - say_hi - Simple greeting (any auth)")
|
||||
log.Println(" - get_user_info - Get user info (read scope)")
|
||||
log.Println(" - create_resource - Create resource (write scope)")
|
||||
log.Println(" - say_hi - Simple greeting (any auth)")
|
||||
log.Println(" - get_user_info - Get user info (read scope)")
|
||||
log.Println(" - create_resource - Create resource (write scope)")
|
||||
log.Println()
|
||||
log.Println("Example usage:")
|
||||
log.Println(" # Generate a token")
|
||||
|
|
|
|||
Loading…
Reference in a new issue