kubernetes/kops · error
decoding authorization token: %w
Error message
decoding authorization token: %w
What it means
VerifyToken expects the incoming authorization token to be a base64-encoded gcetpm.AuthToken JSON prefixed with GCETPMAuthenticationTokenPrefix. If base64.StdEncoding.DecodeString fails on the prefix-stripped value, the token is malformed and cannot even be parsed. This is a client-supplied data validation failure.
Source
Thrown at upup/pkg/fi/cloudup/gce/tpm/gcetpmverifier/tpmverifier.go:85
computeClient: computeClient,
capiManager: capiManager,
}, nil
}
var _ bootstrap.Verifier = (*tpmVerifier)(nil)
func (v *tpmVerifier) VerifyToken(ctx context.Context, rawRequest *http.Request, authToken string, body []byte) (*bootstrap.VerifyResult, error) {
// Reminder: we shouldn't trust any data we get from the client until we've checked the signature (and even then...)
// Thankfully the GCE SDK does seem to escape the parameters correctly, for example.
if !strings.HasPrefix(authToken, gcetpm.GCETPMAuthenticationTokenPrefix) {
return nil, bootstrap.ErrNotThisVerifier
}
authToken = strings.TrimPrefix(authToken, gcetpm.GCETPMAuthenticationTokenPrefix)
tokenBytes, err := base64.StdEncoding.DecodeString(authToken)
if err != nil {
return nil, fmt.Errorf("decoding authorization token: %w", err)
}
token := &gcetpm.AuthToken{}
if err = json.Unmarshal(tokenBytes, token); err != nil {
return nil, fmt.Errorf("unmarshalling authorization token: %w", err)
}
tokenData := gcetpm.AuthTokenData{}
if err := json.Unmarshal(token.Data, &tokenData); err != nil {
return nil, fmt.Errorf("unmarshalling authorization token data: %w", err)
}
// Guard against replay attacks
if tokenData.Audience != gcetpm.AudienceNodeAuthentication {
return nil, fmt.Errorf("incorrect Audience")
}
timeSkew := math.Abs(time.Since(time.Unix(tokenData.Timestamp, 0)).Seconds())
if timeSkew > float64(v.opt.MaxTimeSkew) {View on GitHub (pinned to 4c8573c808)
Solutions
- Regenerate the token with the matching kops/gcetpm version on the node
- Verify both signer and verifier use the same GCETPMAuthenticationTokenPrefix and encoding
- Ensure the full token string reaches the verifier (no truncation by proxies/headers)
- Check that the client uses base64.StdEncoding (not RawURLEncoding) when constructing the token
- Confirm the client is actually the TPM authenticator and not sending a different credential type
Defensive patterns
Strategy: validation
Validate before calling
authHeader := r.Header.Get("Authorization")
if !strings.HasPrefix(authHeader, gcetpm.GCETPMAuthenticationTokenPrefix) {
return bootstrap.ErrNotThisVerifier
}
b64 := strings.TrimPrefix(authHeader, gcetpm.GCETPMAuthenticationTokenPrefix)
if _, err := base64.StdEncoding.DecodeString(b64); err != nil {
return fmt.Errorf("client sent non-base64 token")
} Type guard
func isValidTPMToken(header string) bool {
if !strings.HasPrefix(header, gcetpm.GCETPMAuthenticationTokenPrefix) {
return false
}
_, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(header, gcetpm.GCETPMAuthenticationTokenPrefix))
return err == nil
} Try / catch
token, err := verifier.VerifyToken(ctx, rawToken, request)
if err != nil {
if strings.Contains(err.Error(), "decoding authorization token") {
return fmt.Errorf("malformed token from node; check client version/format: %w", err)
}
return err
} Prevention
- Keep signer and verifier binaries on the same kops release
- Never truncate or rewrite the Authorization header in proxies
- Validate token format client-side before sending
- Use the standard CreateToken output unmodified
When it happens
Trigger: A node sends an Authorization token whose value after the prefix is not valid standard base64: truncated token, token produced by a different/newer client format, token double-encoded or with URL-safe base64 instead of StdEncoding, or garbage/corrupted bytes in transit.
Common situations: Version skew between kops node binary (signer) and control-plane (verifier) changing token format; a proxy or middleware mangling the header; client sending an empty or differently formatted token; manual testing with curl pasting an incorrect token.
Related errors
- unmarshalling authorization token: %w
- failed to get GCE RSA attestation key from TPM: %w
- failed to marshal token data: %w
- failed to marshal token: %w
- unmarshalling authorization token data: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/d75d860bf3a82bdd.
Report an issue: GitHub.