WithScopeChallenge creates a new middleware that determines if an OAuth request contains sufficient scopes to complete the request and returns a scope challenge if not.
(oauthCfg *oauth.Config, scopeFetcher scopes.FetcherInterface)
| 17 | // WithScopeChallenge creates a new middleware that determines if an OAuth request contains sufficient scopes to |
| 18 | // complete the request and returns a scope challenge if not. |
| 19 | func WithScopeChallenge(oauthCfg *oauth.Config, scopeFetcher scopes.FetcherInterface) func(http.Handler) http.Handler { |
| 20 | return func(next http.Handler) http.Handler { |
| 21 | fn := func(w http.ResponseWriter, r *http.Request) { |
| 22 | ctx := r.Context() |
| 23 | |
| 24 | // Skip health check endpoints |
| 25 | if r.URL.Path == "/_ping" { |
| 26 | next.ServeHTTP(w, r) |
| 27 | return |
| 28 | } |
| 29 | |
| 30 | // Get user from context |
| 31 | tokenInfo, ok := ghcontext.GetTokenInfo(ctx) |
| 32 | if !ok { |
| 33 | next.ServeHTTP(w, r) |
| 34 | return |
| 35 | } |
| 36 | |
| 37 | // Only check OAuth tokens - scope challenge allows OAuth apps to request additional scopes |
| 38 | if tokenInfo.TokenType != utils.TokenTypeOAuthAccessToken { |
| 39 | next.ServeHTTP(w, r) |
| 40 | return |
| 41 | } |
| 42 | |
| 43 | // Try to use pre-parsed MCP method info first (performance optimization) |
| 44 | // This avoids re-parsing the JSON body if WithMCPParse middleware ran earlier |
| 45 | var toolName string |
| 46 | if methodInfo, ok := ghcontext.MCPMethod(ctx); ok && methodInfo != nil { |
| 47 | // Only check tools/call requests |
| 48 | if methodInfo.Method != "tools/call" { |
| 49 | next.ServeHTTP(w, r) |
| 50 | return |
| 51 | } |
| 52 | toolName = methodInfo.ItemName |
| 53 | } else { |
| 54 | // Fallback: parse the request body directly |
| 55 | body, err := io.ReadAll(r.Body) |
| 56 | if err != nil { |
| 57 | next.ServeHTTP(w, r) |
| 58 | return |
| 59 | } |
| 60 | r.Body = io.NopCloser(bytes.NewReader(body)) |
| 61 | |
| 62 | var mcpRequest struct { |
| 63 | JSONRPC string `json:"jsonrpc"` |
| 64 | Method string `json:"method"` |
| 65 | Params struct { |
| 66 | Name string `json:"name,omitempty"` |
| 67 | Arguments map[string]any `json:"arguments,omitempty"` |
| 68 | } `json:"params"` |
| 69 | } |
| 70 | |
| 71 | err = json.Unmarshal(body, &mcpRequest) |
| 72 | if err != nil { |
| 73 | next.ServeHTTP(w, r) |
| 74 | return |
| 75 | } |
| 76 |
no test coverage detected