DEV Community

rmb
rmb

Posted on

Stop pasting JWTs into jwt.io

You're debugging an authentication issue. The frontend is getting a 403. You copy the JWT from the Authorization header, open jwt.io in a new tab, paste it in, and check the claims.

Most developers do this multiple times a week. I did too.

The problem: jwt.io is a third-party website. When you paste a token there, you're sending your authentication credential to their servers.

Here's what actually happens when you paste into jwt.io:

The token appears in their server logs. It's in the referrer headers if you navigated from somewhere. It may be in Cloudflare or CDN edge cache logs. Their servers receive it at minimum for the TLS handshake. You have no visibility into their logging or retention practices.

None of that is jwt.io's fault – they're a legitimate tool and they've been clear about their security model. The issue is that production tokens with real claims (user IDs, permission scopes, email addresses, or API credentials embedded in custom claims) probably shouldn't transit through third-party infrastructure at all.


Why it feels fine but isn't

JWT payloads are Base64url-encoded, not encrypted. The header and payload are readable to anyone. That's by design – JWTs are for integrity, not confidentiality. The signature is what prevents tampering; the contents are intentionally readable.

This means decoding a JWT doesn't require any server-side computation. Your browser can do it in one line.

Open your browser console right now and run:

const token = 'your.jwt.here'
const [header, payload] = token.split('.').slice(0, 2)
console.log(JSON.parse(atob(payload.replace(/-/g, '+').replace(/_/g, '/'))))
Enter fullscreen mode Exit fullscreen mode

That's it. No library. No server. No upload. The entire decode operation happens in your browser's JavaScript runtime.

You can also do this:

// Paste this function anywhere
function decodeJWT(token) {
  const parts = token.split('.')
  const decode = str => JSON.parse(atob(str.replace(/-/g, '+').replace(/_/g, '/')))
  return {
    header: decode(parts[0]),
    payload: decode(parts[1]),
    signature: parts[2] // Can't decode without the secret key
  }
}
Enter fullscreen mode Exit fullscreen mode

When tokens contain things that actually matter

The real risk isn't a short-lived access token for a public API. It's:

  • Service account tokens – Long-lived, often stored in CI/CD pipelines, granting broad API access
  • Refresh tokens embedded in JWTs – Some auth systems encode refresh credentials in custom claims
  • Internal service tokens – Tokens for your internal microservices that contain environment-specific URLs or config
  • Tokens with PII in claims – Email addresses, user IDs, phone numbers in the payload
  • Tokens used for high-privilege operations – Admin access, billing actions, data exports

For these, the transit risk is real. A compromised token for an internal admin service is more valuable to an attacker than you'd think.


The no-upload alternative

If you want a full UI with field labeling, expiration parsing, and copy buttons, there are client-side decoders that run entirely in your browser.

brevio JWT Decoder is one – it uses the same atob approach in the browser console, just with a UI. The difference from jwt.io: no network request is made when you decode. Open DevTools → Network tab and verify this yourself; you'll see no outbound request after the initial page load.

Squoosh, CyberChef (self-hosted), and browser extensions like jwt-inspector are other options in the "stays local" category.


The real question

When you copy a JWT from a production request and paste it somewhere, ask: what service did this token come from, what can it do, and how long is it valid?

If it's a 15-minute access token for read-only data on a public API, the risk is low. If it's a 24-hour admin token with write access to production data, pasting it into any external tool is a security incident waiting to happen.

The browser console one-liner takes three seconds and involves zero third parties. Default to that.


For developers who handle confidential files and sensitive data, brevio.pro offers browser-only tools for PDF processing, image compression, JSON formatting, and JWT decoding — nothing leaves your browser.

Top comments (0)