Jon Allured

Computer Programmer, Whiskey Drinker, Comic Book Reader

Decoding JWT Tokens

published 09/10/24

While doing some troubleshooting today at work it occurred to me that I could very easily create a page that decodes JWT tokens so I did it.

What I Used to Do

For years I've used https://jwt.io for this - they have a very convenient decoder right on the homepage. The problem is that by definition I'm pasting something sensitive into a website on the Internet. This is really not a very good idea.

Making My Own Decoder

I knew that I would use my Rails app Monolithium for this so how would I do it?

My first thought was to use a form. I could have a page with a textarea that POSTed to the server and then I could decode on the server and render the response. After thinking that approach through I abandoned it. One thing I wanted to avoid was any traces of the actual tokens. If I used a form that POSTed then I'd want to redirect to a GET and...what - persist the token between requests? Write the token to the session? A cookie?

Use an API Endpoint

At this point I thought that a much better approach would be to create a GET endpoint on my server and have the page I create hit that for the decoded results. That way everything is stateless and nothing would be persisted.

I sketched out an endpoint like this:

GET /api/v1/decode_jwt?token=eyJhbGciOiJub25lIn0.eyJmb28iOiJiYXIifQ.

With a response that looks like this:

{
  "headers": { "alg": "none" },
  "payload": { "foo": "bar" },
  "token": "eyJhbGciOiJub25lIn0.eyJmb28iOiJiYXIifQ."
}

I whipped up some request specs for the invalid case and then implemented this very basic endpoint.

Use Stimulus for The Page

Now it was time to implement the page and connect it to this endpoint. I wanted to use Stimulus so I could get some more experience with it. The HTML I envisioned went something like this:

<section>
  <textarea></textarea>
  <pre>
    <code></code>
  </pre>
</section>

The section would be connected to the Stimulus controller. The textarea would be a target whose value would be the actual token and the code element would be where I rendered the results.

The docs were super helpful and I was able to connect all the pieces pretty quickly.

Finished Product

The PR I opened has all the details but honestly there's not much there. This was pretty easy to do and looks like this:

Decode JWT Screenshot

click for bigger

I don't expect I'll do much more here but now I can paste in JWT tokens to decode without any guilt that I'm possibly doing something that's not secure.