{"record":{"id":"c2f511d82308a05a","repo":"yudai/gotty","slug":"authorization-failed","errorCode":null,"errorMessage":"authorization failed","messagePattern":"authorization failed","errorType":"http","errorClass":null,"httpStatus":401,"severity":"warning","filePath":"server/middleware.go","lineNumber":44,"sourceCode":"func (server *Server) wrapBasicAuth(handler http.Handler, credential string) http.Handler {\n\treturn http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n\t\ttoken := strings.SplitN(r.Header.Get(\"Authorization\"), \" \", 2)\n\n\t\tif len(token) != 2 || strings.ToLower(token[0]) != \"basic\" {\n\t\t\tw.Header().Set(\"WWW-Authenticate\", `Basic realm=\"GoTTY\"`)\n\t\t\thttp.Error(w, \"Bad Request\", http.StatusUnauthorized)\n\t\t\treturn\n\t\t}\n\n\t\tpayload, err := base64.StdEncoding.DecodeString(token[1])\n\t\tif err != nil {\n\t\t\thttp.Error(w, \"Internal Server Error\", http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\tif credential != string(payload) {\n\t\t\tw.Header().Set(\"WWW-Authenticate\", `Basic realm=\"GoTTY\"`)\n\t\t\thttp.Error(w, \"authorization failed\", http.StatusUnauthorized)\n\t\t\treturn\n\t\t}\n\n\t\tlog.Printf(\"Basic Authentication Succeeded: %s\", r.RemoteAddr)\n\t\thandler.ServeHTTP(w, r)\n\t})\n}\n","sourceCodeStart":26,"sourceCodeEnd":52,"githubUrl":"https://github.com/yudai/gotty/blob/a080c85cbc59226c94c6941ad8c395232d72d517/server/middleware.go#L26-L52","documentation":"GoTTY's wrapBasicAuth middleware in server/middleware.go:44 returns HTTP 401 'authorization failed' when the Base64-decoded Authorization payload does not exactly equal the credential string the server was started with (-credential user:pass). The comparison `credential != string(payload)` is a plain string match, so any mismatch in username, password, or the 'user:pass' combined format rejects the request and sets the WWW-Authenticate: Basic realm=\"GoTTY\" challenge.","triggerScenarios":"A request sends a validly Base64-encoded Basic header whose decoded value is not exactly the configured credential: wrong password, wrong username, missing the 'username:password' colon format (sending just 'password'), or the server was started with a different -credential value than the client uses.","commonSituations":"Stale credentials in client config or environment variables after a server restart with a new -credential flag, URL special characters in a password that shell-encode differently than expected, a reverse proxy stripping or rewriting Authorization headers, clients encoding 'user:pass ' with a trailing space/newline, or team members sharing an encoded token generated from different credentials.","solutions":["Re-encode the exact expected value: printf '%s' 'user:pass' | base64 and send that in 'Authorization: Basic <token>' (or use curl -u user:pass)","Verify the credential the server was started with (the -credential flag / config) matches what the client is sending, including case and any special characters","Confirm the Authorization header survives intermediaries; test directly against the GoTTY port bypassing proxies","Inspect for hidden whitespace/newlines in the encoded token (base64 with line wrapping) and strip them"],"exampleFix":"// before\nreq.Header.Set(\"Authorization\", \"Basic \"+base64.StdEncoding.EncodeToString([]byte(\"wrongpass\")))\n// 401 authorization failed\n\n// after\ncred := \"user:pass\" // must match server's -credential exactly\nreq.SetBasicAuth(\"user\", \"pass\") // sends Basic base64(\"user:pass\")","handlingStrategy":"validation","validationCode":"expected := \"user:pass\" // must match server -credential exactly\nif base64.StdEncoding.EncodeToString([]byte(expected)) != token {\n\tlog.Printf(\"credential mismatch: re-encode from the server's configured credential\")\n}","typeGuard":null,"tryCatchPattern":"resp, err := client.Do(req)\nif err == nil && resp.StatusCode == http.StatusUnauthorized {\n\t// 401 'authorization failed': check credential vs server's -credential,\n\t// refresh credentials, then retry once with corrected values\n}","preventionTips":["Keep server -credential and client credentials in one shared source (env var/config file) to avoid drift","Use a client library helper (SetBasicAuth, curl -u) rather than hand-encoding","After changing the server's credential, update and re-test all clients","Verify against the server directly before blaming proxies; check for header-stripping middleware on reverse proxies"],"tags":["http","authentication","basic-auth","credentials","gotty"],"backgroundTag":"basic-auth-credentials-rejected","analyzedSha":"a080c85cbc59226c94c6941ad8c395232d72d517","analyzedAt":"2026-09-02T16:42:38.150Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}