github.com/anthropics/anthropic-sdk-go@v1.70.1/config/oautherr.go (about)

     1  package config
     2  
     3  import "encoding/json"
     4  
     5  // OAuthErrorBodyMaxLen caps the error body length embedded in OAuth-endpoint
     6  // failure error messages. Token-endpoint responses are untrusted and are
     7  // routinely captured in logs; the cap covers identity-provider proxies that
     8  // concatenate upstream messages into error_description.
     9  const OAuthErrorBodyMaxLen = 2000
    10  
    11  // oauthErrorAllowedKeys is the RFC 6749 §5.2 allowlist surfaced in
    12  // user-facing errors. Any other key is dropped — providers have been seen
    13  // to echo back the assertion JWT or a partially-minted token, neither of
    14  // which may appear in logs. error_description is attacker-controllable
    15  // free-form text; callers must treat redacted output as untrusted.
    16  var oauthErrorAllowedKeys = []string{
    17  	"error",
    18  	"error_description",
    19  	"error_uri",
    20  }
    21  
    22  // RedactOAuthErrorBody returns a safe-to-log form of an OAuth token endpoint
    23  // failure body. If the body parses as a JSON object, only the RFC 6749 §5.2
    24  // allowed keys are kept. Non-JSON bodies are replaced with a redaction
    25  // placeholder. Either way the result is truncated to [OAuthErrorBodyMaxLen].
    26  func RedactOAuthErrorBody(body string) string {
    27  	var obj map[string]any
    28  	// err only — Unmarshal("null") sets obj=nil with no error; nil filters to {}.
    29  	if err := json.Unmarshal([]byte(body), &obj); err == nil {
    30  		filtered := make(map[string]any, len(oauthErrorAllowedKeys))
    31  		for _, k := range oauthErrorAllowedKeys {
    32  			if v, present := obj[k]; present {
    33  				filtered[k] = v
    34  			}
    35  		}
    36  		if b, err := json.Marshal(filtered); err == nil {
    37  			body = string(b)
    38  		}
    39  	} else {
    40  		body = "[redacted; not a JSON error response]"
    41  	}
    42  	if len(body) > OAuthErrorBodyMaxLen {
    43  		body = body[:OAuthErrorBodyMaxLen] + "...[truncated]"
    44  	}
    45  	return body
    46  }