flashman
← All posts

Base64url padding: debug signature integration bugs

Fix Base64url padding bugs by comparing encoders, JWT segments, webhook signatures, URL parameters, and safe fixtures before integrations fail in prod.

2026-07-20 · 6 min read · Rahul Chitturi

  • base64
  • webhooks
  • debugging

Base64url is close enough to standard Base64 to fool reviewers, but the small differences matter. URL-safe alphabets swap characters, padding may be omitted, and some libraries normalize inputs before you ever see the mismatch.

The result is a webhook signature that validates in one language and fails in another, a JWT segment that decodes locally but not in production, or a callback parameter that breaks after being copied through a URL parser.

Identify the encoding variant

Before changing secrets or hash logic, write down which bytes are signed and which encoding is expected at each boundary. Signature failures are often caused by representation drift rather than cryptography.

  • Check whether the provider sends standard Base64 or Base64url
  • Confirm if trailing = padding is required, optional, or forbidden
  • Compare the raw signed message with the decoded payload
  • Verify URL decoding does not convert plus signs, slashes, or percent escapes unexpectedly

Build safe reproductions

Use a fake secret and a tiny sample payload to reproduce the mismatch. If the failure survives with synthetic data, you can share the fixture in code review without exposing production tokens, request bodies, or signing keys.

Keep the test focused on byte-for-byte input, digest algorithm, output encoding, and padding policy. Mixing those questions together makes every signature error look like a bad secret.

A Flashman workflow

Use the Base64 tool to compare encoded forms, the JWT decoder for safe token segments, the hash tool for synthetic signature checks, and the URL encoder when callback parameters are part of the path.

The final note should state the exact mismatch: alphabet, padding, bytes signed, URL decoding, hash algorithm, or library default. That clarity prevents future integrations from repeating the same failure.

Try these tools