{"record":{"id":"c1085e2517d3ff27","repo":"vxcontrol/pentagi","slug":"bearer-scheme-must-be-used","errorCode":null,"errorMessage":"bearer scheme must be used","messagePattern":"bearer scheme must be used","errorType":"http","errorClass":null,"httpStatus":401,"severity":"error","filePath":"backend/pkg/server/auth/auth_middleware.go","lineNumber":203,"sourceCode":"\tc.Set(\"uname\", uname.(string))\n\n\tif slices.Contains(prms, PrivilegeAutomation) {\n\t\tc.Set(\"cpt\", \"automation\")\n\t}\n\n\treturn authResultOk, nil\n}\n\nconst PrivilegeAutomation = \"pentagi.automation\"\n\nfunc (p *AuthMiddleware) tryProtoTokenAuthentication(c *gin.Context) (authResult, error) {\n\tauthHeader := c.Request.Header.Get(\"Authorization\")\n\tif authHeader == \"\" {\n\t\treturn authResultSkip, errors.New(\"token required\")\n\t}\n\n\tif !strings.HasPrefix(authHeader, \"Bearer \") {\n\t\treturn authResultSkip, errors.New(\"bearer scheme must be used\")\n\t}\n\ttoken := authHeader[7:]\n\tif token == \"\" {\n\t\treturn authResultSkip, errors.New(\"token can't be empty\")\n\t}\n\n\t// skip validation if using default salt (for backward compatibility)\n\tif p.globalSalt == \"\" || p.globalSalt == \"salt\" {\n\t\treturn authResultSkip, errors.New(\"token validation disabled with default salt\")\n\t}\n\n\t// try to validate as API token first (new format with JWT signing key)\n\tapiClaims, apiErr := ValidateAPIToken(token, p.globalSalt)\n\tif apiErr != nil {\n\t\treturn authResultFail, errors.New(\"token is invalid\")\n\t}\n\n\t// check token status and get privileges through cache","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/server/auth/auth_middleware.go#L185-L221","documentation":"tryProtoTokenAuthentication in backend/pkg/server/auth/auth_middleware.go rejects an Authorization header that is present but does not start with the exact prefix \"Bearer \". The middleware only accepts bearer-token authentication for programmatic API access; any other auth scheme (Basic, raw token, lowercase \"bearer\") is skipped so other auth paths can be tried, and this error records why. It is a request-shape error, not a token-validity error.","triggerScenarios":"Sending an Authorization header whose value does not begin with \"Bearer \" (case-sensitive, with a single space), e.g. `Authorization: Basic ...`, `Authorization: bearer abc123`, or `Authorization: <raw-token>` with no scheme at all, on an endpoint guarded by this middleware.","commonSituations":"Copy-pasting a token without the scheme; HTTP clients that auto-attach Basic auth; hand-rolled curl calls omitting the word Bearer; proxy or SDK that lowercases the scheme; using a session cookie flow expectation against the token endpoint.","solutions":["Set the header exactly to `Authorization: Bearer <api-token>` (capital B, one space).","If using curl, use `-H \"Authorization: Bearer $TOKEN\"` instead of `-u` or a bare token header.","If your client library has an auth helper (e.g. axios AuthInterceptor with token type 'Bearer'), configure it rather than writing the header manually.","If you intended cookie/session auth, remove the Authorization header so the middleware falls through to session authentication."],"exampleFix":"// before\nreq.Header.Set(\"Authorization\", apiKey)\n\n// after\nreq.Header.Set(\"Authorization\", \"Bearer \"+apiKey)","handlingStrategy":"validation","validationCode":"const auth = headers[\"Authorization\"];\nif (auth !== undefined && !auth.startsWith(\"Bearer \")) {\n  throw new Error(\"Authorization header must use the Bearer scheme\");\n}","typeGuard":"function isBearerHeader(v: string | undefined): v is string {\n  return typeof v === \"string\" && v.startsWith(\"Bearer \");\n}","tryCatchPattern":"try {\n  const res = await api.call();\n} catch (e) {\n  if (is401(e) && /bearer scheme/i.test(e.message)) {\n    fixAuthorizationHeader();\n  }\n  throw e;\n}","preventionTips":["Always build the header via an auth helper that emits \"Bearer <token>\".","Never hand-concatenate the Authorization value without the scheme constant.","Add an integration test asserting the exact header string sent."],"tags":["http","authentication","go","authorization-header"],"backgroundTag":"missing-bearer-scheme","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}