From 539da18af975be9f4e3a793ae395b677ee12a089 Mon Sep 17 00:00:00 2001 From: Jonathan Amsterdam Date: Thu, 18 Sep 2025 13:20:40 -0400 Subject: [PATCH 1/2] docs: add auth and security sections --- docs/protocol.md | 60 +++++++++++++++++++++++++++++++++-- internal/docs/protocol.src.md | 55 ++++++++++++++++++++++++++++++-- 2 files changed, 111 insertions(+), 4 deletions(-) diff --git a/docs/protocol.md b/docs/protocol.md index 75c5d127..ea058622 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -8,7 +8,12 @@ 1. [Custom transports](#custom-transports) 1. [Concurrency](#concurrency) 1. [Authorization](#authorization) + 1. [Server](#server) + 1. [Client](#client) 1. [Security](#security) + 1. [Confused Deputy](#confused-deputy) + 1. [Token Passthrough](#token-passthrough) + 1. [Session Hijacking](#session-hijacking) 1. [Utilities](#utilities) 1. [Cancellation](#cancellation) 1. [Ping](#ping) @@ -232,11 +237,62 @@ for more background. ## Authorization - +### Server + +To write an MCP server that performs authorization, +use [`RequireBearerToken`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#RequireBearerToken). +This function is middleware that wraps an HTTP handler, such as the one returned +by [`NewStreamableHTTPHandler`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#NewStreamableHTTPHandler), to provide support for verifying bearer tokens. +The middleware function checks every request for an Authorization header with a bearer token, +and invokes the +[`TokenVerifier`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#TokenVerifier) + passed to `RequireBearerToken` to parse the token and perform validation. +The middleware function checks expiration and scopes (if they are provided in +[`RequireBearerTokenOptions.Scopes`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#RequireBearerTokenOptions.Scopes)), so the +`TokenVerifer` doesn't have to. +If [`RequireBearerTokenOptions.ResourceMetadataURL`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#RequireBearerTokenOptions.ResourceMetadataURL) is set and verification fails, +the middleware function sets the WWW-Authenticate header as required by the [Protected Resource +Metadata spec](https://datatracker.ietf.org/doc/html/rfc9728). + +The [auth middleware example](https://github.com/modelcontextprotocol/go-sdk/tree/main/examples/server/auth-middleware) shows how to implement authorization for both JWT tokens and API keys. + +### Client + +Client-side OAuth is implemented by setting +[`StreamableClientTransport.HTTPClient`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk@v0.5.0/mcp#StreamableClientTransport.HTTPClient) to a custom [`http.Client`](https://pkg.go.dev/net/http#Client) +Additional support is forthcoming. ## Security - +Here we discuss the mitigations described under +the MCP spec's [Security Best Practices](https://modelcontextprotocol.io/specification/2025-06-18/basic/security_best_practices) section, and how we handle them. + +### Confused Deputy + +The [mitigation](https://modelcontextprotocol.io/specification/2025-06-18/basic/security_best_practices#mitigation), obtaining user consent for dynamically registered clients, +happens on the MCP client. At present we don't provide client-side OAuth support. + + +### Token Passthrough + +The [mitigation](https://modelcontextprotocol.io/specification/2025-06-18/basic/security_best_practices#mitigation-2), accepting only tokens that were issued for the server, depends on the structure +of tokens and is the responsibility of the +[`TokenVerifier`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#TokenVerifier) +provided to +[`RequireBearerToken`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#RequireBearerToken). + +### Session Hijacking + +The [mitigations](https://modelcontextprotocol.io/specification/2025-06-18/basic/security_best_practices#mitigation-3) are as follows: + +- _Verify all inbound requests_. The [`RequireBearerToken`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#RequireBearerToken) +middleware function will verify all HTTP requests that it receives. It is the +user's responsibility to wrap that function around all handlers in their server. + +- _Secure session IDs_. This SDK generates cryptographically secure session IDs by default. + +- _Binding session IDs to user information_. This is an application requirement, out of scope +for the SDK. ## Utilities diff --git a/internal/docs/protocol.src.md b/internal/docs/protocol.src.md index 2bb954bf..e780f477 100644 --- a/internal/docs/protocol.src.md +++ b/internal/docs/protocol.src.md @@ -164,11 +164,62 @@ for more background. ## Authorization - +### Server + +To write an MCP server that performs authorization, +use [`RequireBearerToken`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#RequireBearerToken). +This function is middleware that wraps an HTTP handler, such as the one returned +by [`NewStreamableHTTPHandler`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#NewStreamableHTTPHandler), to provide support for verifying bearer tokens. +The middleware function checks every request for an Authorization header with a bearer token, +and invokes the +[`TokenVerifier`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#TokenVerifier) + passed to `RequireBearerToken` to parse the token and perform validation. +The middleware function checks expiration and scopes (if they are provided in +[`RequireBearerTokenOptions.Scopes`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#RequireBearerTokenOptions.Scopes)), so the +`TokenVerifer` doesn't have to. +If [`RequireBearerTokenOptions.ResourceMetadataURL`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#RequireBearerTokenOptions.ResourceMetadataURL) is set and verification fails, +the middleware function sets the WWW-Authenticate header as required by the [Protected Resource +Metadata spec](https://datatracker.ietf.org/doc/html/rfc9728). + +The [auth middleware example](https://github.com/modelcontextprotocol/go-sdk/tree/main/examples/server/auth-middleware) shows how to implement authorization for both JWT tokens and API keys. + +### Client + +Client-side OAuth is implemented by setting +[`StreamableClientTransport.HTTPClient`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk@v0.5.0/mcp#StreamableClientTransport.HTTPClient) to a custom [`http.Client`](https://pkg.go.dev/net/http#Client) +Additional support is forthcoming. ## Security - +Here we discuss the mitigations described under +the MCP spec's [Security Best Practices](https://modelcontextprotocol.io/specification/2025-06-18/basic/security_best_practices) section, and how we handle them. + +### Confused Deputy + +The [mitigation](https://modelcontextprotocol.io/specification/2025-06-18/basic/security_best_practices#mitigation), obtaining user consent for dynamically registered clients, +happens on the MCP client. At present we don't provide client-side OAuth support. + + +### Token Passthrough + +The [mitigation](https://modelcontextprotocol.io/specification/2025-06-18/basic/security_best_practices#mitigation-2), accepting only tokens that were issued for the server, depends on the structure +of tokens and is the responsibility of the +[`TokenVerifier`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#TokenVerifier) +provided to +[`RequireBearerToken`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#RequireBearerToken). + +### Session Hijacking + +The [mitigations](https://modelcontextprotocol.io/specification/2025-06-18/basic/security_best_practices#mitigation-3) are as follows: + +- _Verify all inbound requests_. The [`RequireBearerToken`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/auth#RequireBearerToken) +middleware function will verify all HTTP requests that it receives. It is the +user's responsibility to wrap that function around all handlers in their server. + +- _Secure session IDs_. This SDK generates cryptographically secure session IDs by default. + +- _Binding session IDs to user information_. This is an application requirement, out of scope +for the SDK. ## Utilities From e9423ea1d9e4ee74d116dc7d00057e17fb5dbde4 Mon Sep 17 00:00:00 2001 From: Jonathan Amsterdam Date: Thu, 18 Sep 2025 14:15:34 -0400 Subject: [PATCH 2/2] user comments --- docs/protocol.md | 11 ++++++++--- internal/docs/protocol.src.md | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/docs/protocol.md b/docs/protocol.md index ea058622..e3b9e8c2 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -254,13 +254,13 @@ If [`RequireBearerTokenOptions.ResourceMetadataURL`](https://pkg.go.dev/github.c the middleware function sets the WWW-Authenticate header as required by the [Protected Resource Metadata spec](https://datatracker.ietf.org/doc/html/rfc9728). -The [auth middleware example](https://github.com/modelcontextprotocol/go-sdk/tree/main/examples/server/auth-middleware) shows how to implement authorization for both JWT tokens and API keys. +The [_auth middleware example_](https://github.com/modelcontextprotocol/go-sdk/tree/main/examples/server/auth-middleware) shows how to implement authorization for both JWT tokens and API keys. ### Client Client-side OAuth is implemented by setting [`StreamableClientTransport.HTTPClient`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk@v0.5.0/mcp#StreamableClientTransport.HTTPClient) to a custom [`http.Client`](https://pkg.go.dev/net/http#Client) -Additional support is forthcoming. +Additional support is forthcoming; see #493. ## Security @@ -290,9 +290,14 @@ middleware function will verify all HTTP requests that it receives. It is the user's responsibility to wrap that function around all handlers in their server. - _Secure session IDs_. This SDK generates cryptographically secure session IDs by default. +If you create your own with +[`ServerOptions.GetSessionID`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ServerOptions.GetSessionID), it is your responsibility to ensure they are secure. +If you are using Go 1.24 or above, +we recommend using [`crypto/rand.Text`](https://pkg.go.dev/crypto/rand#Text) - _Binding session IDs to user information_. This is an application requirement, out of scope -for the SDK. +for the SDK. You can create your own session IDs by setting +[`ServerOptions.GetSessionID`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ServerOptions.GetSessionID). ## Utilities diff --git a/internal/docs/protocol.src.md b/internal/docs/protocol.src.md index e780f477..0abd5aa8 100644 --- a/internal/docs/protocol.src.md +++ b/internal/docs/protocol.src.md @@ -181,13 +181,13 @@ If [`RequireBearerTokenOptions.ResourceMetadataURL`](https://pkg.go.dev/github.c the middleware function sets the WWW-Authenticate header as required by the [Protected Resource Metadata spec](https://datatracker.ietf.org/doc/html/rfc9728). -The [auth middleware example](https://github.com/modelcontextprotocol/go-sdk/tree/main/examples/server/auth-middleware) shows how to implement authorization for both JWT tokens and API keys. +The [_auth middleware example_](https://github.com/modelcontextprotocol/go-sdk/tree/main/examples/server/auth-middleware) shows how to implement authorization for both JWT tokens and API keys. ### Client Client-side OAuth is implemented by setting [`StreamableClientTransport.HTTPClient`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk@v0.5.0/mcp#StreamableClientTransport.HTTPClient) to a custom [`http.Client`](https://pkg.go.dev/net/http#Client) -Additional support is forthcoming. +Additional support is forthcoming; see #493. ## Security @@ -217,9 +217,14 @@ middleware function will verify all HTTP requests that it receives. It is the user's responsibility to wrap that function around all handlers in their server. - _Secure session IDs_. This SDK generates cryptographically secure session IDs by default. +If you create your own with +[`ServerOptions.GetSessionID`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ServerOptions.GetSessionID), it is your responsibility to ensure they are secure. +If you are using Go 1.24 or above, +we recommend using [`crypto/rand.Text`](https://pkg.go.dev/crypto/rand#Text) - _Binding session IDs to user information_. This is an application requirement, out of scope -for the SDK. +for the SDK. You can create your own session IDs by setting +[`ServerOptions.GetSessionID`](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk/mcp#ServerOptions.GetSessionID). ## Utilities