snail007/goproxy · error

authorization data error,ERR:%s

Error message

authorization data error,ERR:%s

What it means

BasicAuth extracts the Authorization header and expects exactly two whitespace-separated fields: the scheme (Basic) and the base64 credentials. If strings.Fields(authorization) does not yield exactly 2 fields, it throws "authorization data error,ERR:%s" with the raw header value, closes the connection, and returns. The 401-with-WWW-Authenticate challenge is only sent when the header is missing entirely — a malformed header just errors out.

Source

Thrown at utils/structs.go:320

	return
}
func (req *HTTPRequest) IsHTTPS() bool {
	return req.Method == "CONNECT"
}

func (req *HTTPRequest) BasicAuth() (err error) {

	//log.Printf("request :%s", string(b[:n]))
	authorization, err := req.getHeader("Authorization")
	if err != nil {
		fmt.Fprint((*req.conn), "HTTP/1.1 401 Unauthorized\r\nWWW-Authenticate: Basic realm=\"\"\r\n\r\nUnauthorized")
		CloseConn(req.conn)
		return
	}
	//log.Printf("Authorization:%s", authorization)
	basic := strings.Fields(authorization)
	if len(basic) != 2 {
		err = fmt.Errorf("authorization data error,ERR:%s", authorization)
		CloseConn(req.conn)
		return
	}
	user, err := base64.StdEncoding.DecodeString(basic[1])
	if err != nil {
		err = fmt.Errorf("authorization data parse error,ERR:%s", err)
		CloseConn(req.conn)
		return
	}
	authOk := (*req.basicAuth).Check(string(user))
	//log.Printf("auth %s,%v", string(user), authOk)
	if !authOk {
		fmt.Fprint((*req.conn), "HTTP/1.1 401 Unauthorized\r\n\r\nUnauthorized")
		CloseConn(req.conn)
		err = fmt.Errorf("basic auth fail")
		return
	}
	return

View on GitHub (pinned to e6d6a821db)

Solutions

  1. Check the ERR payload in the error (it contains the exact header value) and fix the client to send `Authorization: Basic base64(user:pass)`.
  2. Verify the client encodes credentials with standard base64 of "username:password" (e.g. `echo -n 'user:pass' | base64`) and prefixes them with "Basic ".
  3. Check for reverse proxies/middleware that mangle or duplicate the Authorization header; strip extra fields upstream.
  4. Ensure only one Authorization header is sent — combined values break the two-field expectation.

Example fix

// before (client)
req.Header.Set("Authorization", "myuser:mypass")

// after (client)
req.SetBasicAuth("myuser", "mypass") // -> Authorization: Basic bXl1c2VyOm15cGFzcw==
Defensive patterns

Strategy: validation

Validate before calling

// client-side pre-check: header must be exactly 'Basic <b64>'
tok := req.Header.Get("Authorization")
fields := strings.Fields(tok)
if len(fields) != 2 || fields[0] != "Basic" {
	return errors.New("Authorization must be exactly: Basic base64(user:pass)")
}
if _, err := base64.StdEncoding.DecodeString(fields[1]); err != nil {
	return fmt.Errorf("credentials are not valid standard base64: %w", err)
}

Try / catch

_, err := utils.NewHTTPRequest(conn, bufSize, true, auth)
if err != nil && strings.HasPrefix(err.Error(), "authorization data error") {
	log.Printf("client sent malformed Authorization header: %v", err)
	// optionally write a 400/401 before closing; conn already closed by library
}

Prevention

When it happens

Trigger: Calling NewHTTPRequest on a proxy with basic auth enabled when the client sends a malformed Authorization header: only the scheme ("Basic") with no credential, extra tokens ("Basic user:pass extra"), or a custom header value without the two-field scheme+token shape.

Common situations: Clients with hand-crafted Authorization headers (typos, missing base64); middleware or API gateways rewriting/adding Authorization fields; double Authorization headers merged into one value; clients sending raw "user:pass" without base64 or scheme.

Related errors


AI-assisted analysis of snail007/goproxy@e6d6a821db (2026-09-03). Data as JSON: /api/errors/ee21fb7c4d7a15b1. Report an issue: GitHub.