MCPcopy Create free account
hub / github.com/modelcontextprotocol/go-sdk / ExchangeToken

Function ExchangeToken

oauthex/token_exchange.go:81–183  ·  view source on GitHub ↗

ExchangeToken performs a token exchange request per RFC 8693 for Enterprise Managed Authorization (SEP-990). It exchanges an identity assertion (typically an ID Token) for an Identity Assertion JWT Authorization Grant (ID-JAG) that can be used to obtain an access token from an MCP Server. The token

(
	ctx context.Context,
	tokenEndpoint string,
	req *TokenExchangeRequest,
	clientCreds *ClientCredentials,
	httpClient *http.Client,
)

Source from the content-addressed store, hash-verified

79// - Extra("scope") may contain the scope if different from the request
80// - Expiry is when the token expires
81func ExchangeToken(
82 ctx context.Context,
83 tokenEndpoint string,
84 req *TokenExchangeRequest,
85 clientCreds *ClientCredentials,
86 httpClient *http.Client,
87) (*oauth2.Token, error) {
88 if tokenEndpoint == "" {
89 return nil, fmt.Errorf("token endpoint is required")
90 }
91 if req == nil {
92 return nil, fmt.Errorf("token exchange request is required")
93 }
94 if clientCreds == nil {
95 return nil, fmt.Errorf("client credentials are required")
96 }
97 if err := clientCreds.Validate(); err != nil {
98 return nil, fmt.Errorf("invalid client credentials: %w", err)
99 }
100
101 // Validate required fields per SEP-990 Section 4.
102 if req.RequestedTokenType == "" {
103 return nil, fmt.Errorf("requested_token_type is required")
104 }
105 if req.Audience == "" {
106 return nil, fmt.Errorf("audience is required")
107 }
108 if req.Resource == "" {
109 return nil, fmt.Errorf("resource is required")
110 }
111 if req.SubjectToken == "" {
112 return nil, fmt.Errorf("subject_token is required")
113 }
114 if req.SubjectTokenType == "" {
115 return nil, fmt.Errorf("subject_token_type is required")
116 }
117
118 // Validate URL schemes to prevent XSS attacks (see #526).
119 if err := checkURLScheme(tokenEndpoint); err != nil {
120 return nil, fmt.Errorf("invalid token endpoint: %w", err)
121 }
122 if err := checkURLScheme(req.Audience); err != nil {
123 return nil, fmt.Errorf("invalid audience: %w", err)
124 }
125 if err := checkURLScheme(req.Resource); err != nil {
126 return nil, fmt.Errorf("invalid resource: %w", err)
127 }
128
129 // Per RFC 6749 Section 3.2, parameters sent without a value (like the empty
130 // "code" parameter) MUST be treated as if they were omitted from the request.
131 // The oauth2 library's Exchange method sends an empty code, but compliant
132 // servers should ignore it.
133 cfg := &oauth2.Config{
134 ClientID: clientCreds.ClientID,
135 Endpoint: oauth2.Endpoint{
136 TokenURL: tokenEndpoint,
137 AuthStyle: oauth2.AuthStyleInParams,
138 },

Callers 2

AuthorizeMethod · 0.92
TestExchangeTokenFunction · 0.85

Calls 2

ValidateMethod · 0.80
checkURLSchemeFunction · 0.70

Tested by 1

TestExchangeTokenFunction · 0.68

Used in the wild real call sites across dependent graphs

searching dependent graphs…