kubernetes/kops · error

unmarshalling authorization token data: %w

Error message

unmarshalling authorization token data: %w

What it means

VerifyToken then unmarshals the inner Data field into gcetpm.AuthTokenData. Failure means the outer token was fine but the signed payload is not the expected structure, so verification must abort before checking audience/timestamp/signature.

Source

Thrown at upup/pkg/fi/cloudup/gce/tpm/gcetpmverifier/tpmverifier.go:95

	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) {
		return nil, fmt.Errorf("incorrect Timestamp %v", tokenData.Timestamp)
	}

	// Verify the token has signed the body content.
	requestHash := sha256.Sum256(body)
	if !bytes.Equal(requestHash[:], tokenData.RequestHash) {
		return nil, fmt.Errorf("incorrect RequestHash")
	}

	// Some basic validation to avoid requesting invalid instances.

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Align versions of the node signer and verifier so AuthTokenData schema matches
  2. Decode the token (base64 -d then jq) and inspect the inner Data structure
  3. Regenerate the token from the current node binary
  4. Roll back a control-plane upgrade that changed gcetpm token format
Defensive patterns

Strategy: validation

Validate before calling

tokenData := gcetpm.AuthTokenData{}
if err := json.Unmarshal(token.Data, &tokenData); err != nil {
    // pre-validate the inner payload before calling the verifier
    return fmt.Errorf("inner token data invalid: %w", err)
}
if tokenData.Audience == "" || tokenData.Timestamp == 0 {
    return fmt.Errorf("token data missing required fields")
}

Type guard

func hasValidTokenDataShape(data []byte) bool {
    var td gcetpm.AuthTokenData
    if err := json.Unmarshal(data, &td); err != nil { return false }
    return td.Audience != "" && td.Timestamp != 0
}

Try / catch

token, err := verifier.VerifyToken(ctx, rawToken, request)
if err != nil && strings.Contains(err.Error(), "unmarshalling authorization token data") {
    return fmt.Errorf("node token schema mismatch; upgrade node: %w", err)
}

Prevention

When it happens

Trigger: json.Unmarshal(token.Data, &tokenData) fails: Data bytes are not valid JSON of AuthTokenData (fields with wrong types, empty Data, truncated inner payload).

Common situations: Version skew where AuthTokenData fields were renamed/retyped between signer and verifier; token produced by an older kops release against a newer control-plane; corrupted or hand-crafted tokens.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/0294618775f79114. Report an issue: GitHub.