{"record":{"id":"093e6b241a5d72df","repo":"github/github-mcp-server","slug":"w-missing-required-authorization-header","errorCode":null,"errorMessage":"%w: missing required Authorization header","messagePattern":"%w: missing required Authorization header","errorType":"validation","errorClass":"mark.ErrBadRequest","httpStatus":401,"severity":"error","filePath":"pkg/utils/token.go","lineNumber":33,"sourceCode":"const (\n\tTokenTypeUnknown TokenType = iota\n\tTokenTypePersonalAccessToken\n\tTokenTypeFineGrainedPersonalAccessToken\n\tTokenTypeOAuthAccessToken\n\tTokenTypeUserToServerGitHubAppToken\n\tTokenTypeServerToServerGitHubAppToken\n)\n\nvar supportedGitHubPrefixes = map[string]TokenType{\n\t\"ghp_\":        TokenTypePersonalAccessToken,            // Personal access token (classic)\n\t\"github_pat_\": TokenTypeFineGrainedPersonalAccessToken, // Fine-grained personal access token\n\t\"gho_\":        TokenTypeOAuthAccessToken,               // OAuth access token\n\t\"ghu_\":        TokenTypeUserToServerGitHubAppToken,     // User access token for a GitHub App\n\t\"ghs_\":        TokenTypeServerToServerGitHubAppToken,   // Installation access token for a GitHub App (a.k.a. server-to-server token)\n}\n\nvar (\n\tErrMissingAuthorizationHeader     = fmt.Errorf(\"%w: missing required Authorization header\", mark.ErrBadRequest)\n\tErrBadAuthorizationHeader         = fmt.Errorf(\"%w: Authorization header is badly formatted\", mark.ErrBadRequest)\n\tErrUnsupportedAuthorizationHeader = fmt.Errorf(\"%w: unsupported Authorization header\", mark.ErrBadRequest)\n)\n\n// oldPatternRegexp is the regular expression for the old pattern of the token.\n// Until 2021, GitHub API tokens did not have an identifiable prefix. They\n// were 40 characters long and only contained the characters a-f and 0-9.\nvar oldPatternRegexp = regexp.MustCompile(`\\A[a-f0-9]{40}\\z`)\n\n// ParseAuthorizationHeader parses the Authorization header from the HTTP request\nfunc ParseAuthorizationHeader(req *http.Request) (tokenType TokenType, token string, _ error) {\n\tauthHeader := req.Header.Get(httpheaders.AuthorizationHeader)\n\tif authHeader == \"\" {\n\t\treturn 0, \"\", ErrMissingAuthorizationHeader\n\t}\n\n\tswitch {\n\t// decrypt dotcom token and set it as token","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/github/github-mcp-server/blob/0ea1f775a7c73eff1bd2e25904d01136756bbfe2/pkg/utils/token.go#L15-L51","documentation":"Sentinel error returned by utils.ParseAuthorizationHeader when the request carries no Authorization header at all. Although it wraps mark.ErrBadRequest ('bad request'), the token middleware special-cases it: instead of a 400 it calls sendAuthChallenge, producing a 401 with a WWW-Authenticate Bearer challenge per the MCP authorization spec so OAuth clients start the flow.","triggerScenarios":"Any HTTP request to a token-protected endpoint without an Authorization header: bare curl, an MCP client with no token configured, or a proxy that strips the header.","commonSituations":"First requests from remote MCP clients before OAuth completes; curl tests forgetting -H 'Authorization: Bearer ...'; reverse proxies or service meshes dropping the header.","solutions":["Send Authorization: Bearer <GitHub token> on every request to protected endpoints","As an OAuth client, treat the 401 + WWW-Authenticate response as the trigger to run the OAuth flow, then retry","Check intermediaries (nginx auth_request, meshes, gateways) are not stripping Authorization"],"exampleFix":"# before\ncurl http://localhost:8080/api/mcp -d @req.json\n\n# after\ncurl http://localhost:8080/api/mcp -H \"Authorization: Bearer ghp_xxxx\" -d @req.json","handlingStrategy":"validation","validationCode":"// client side, before sending\nif token == \"\" {\n\treturn errors.New(\"no token configured: the server will answer 401 with a Bearer challenge\")\n}\nreq.Header.Set(\"Authorization\", \"Bearer \"+token)","typeGuard":"func isMissingAuthHeader(err error) bool {\n\treturn errors.Is(err, utils.ErrMissingAuthorizationHeader)\n}","tryCatchPattern":"if err != nil {\n\tif errors.Is(err, utils.ErrMissingAuthorizationHeader) {\n\t\t// middleware already sent 401 + WWW-Authenticate: start/continue the OAuth flow, then retry\n\t} else {\n\t\t// 400-class header problems: fix the token, do not challenge\n\t}\n}","preventionTips":["Set the token once on the client transport (DefaultHeader/SetAuthToken) so every call carries it","Treat 401 + WWW-Authenticate as a flow trigger, not a hard failure","Smoke-test endpoints with an authenticated request in CI"],"tags":["http","authentication","mcp","middleware","oauth"],"backgroundTag":null,"analyzedSha":"0ea1f775a7c73eff1bd2e25904d01136756bbfe2","analyzedAt":"2026-08-15T18:10:19.804Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}