Sitemap
TechVerito

All about Technology, Software Craftsmanship, Agile

✨ Secure JWT Authentication in Go Using JWKs

--

Security is a cornerstone of every modern application. And when it comes to authentication, JWT (JSON Web Token) is one of the most reliable solutions. But managing keys securely? That’s where JWK (JSON Web Key) shines. It helps manage and share keys safely, especially with asymmetric encryption.

One key signs the token, another verifies it — simple, secure, and scalable

🚓 “License, registration, and your kid, please."

In this post, I’ll show you how I built a simple CLI tool in Go that:

  • Generates JWTs using JWK-based private keys
  • Verifies JWTs using public keys
  • Interactive menu using Cobra CLI

Let’s dive in! 🌊

You can get this code link on github — https://github.com/hrushya07/jwk-jwt-auth/

🔐 Why JWT with JWK?

Before jumping into code, let’s get a quick overview:

  • JWT is a stateless way to transmit user claims between parties.
  • JWK provides a secure and standard way to represent cryptographic keys in JSON format.
  • Private keys sign the JWT.
  • Public keys verify the JWT signature.

This will help you rotate keys, handle multiple key IDs (kids), and expose a JWKS endpoint so others can verify your tokens.

🧠 Project Structure

jwk-jwt-auth/
├── cmd/ # CLI with Cobra
├── internal/
│ └── manager/ # JWK and JWT managers
├── service/ # Auth service layer
├── model/ # User model
└── main.go

🧰 Key Components

1. Jwk Manager – Your Keysmith 🔑

Here, IJwkManager defines what actions our key manager can perform: initializing key sets, getting private keys, and sharing public keys. JwkManager is the actual manager that holds the keys and implements those actions. The function NewJwkManager simply creates a new JwkManager ready to manage keys.

I. InitializeJwkSet — Building Your Key Vault

Now, let’s talk about how we build the vault. This function generates several RSA private keys, each with its unique Key ID (e.g., key-0, key-1). It’s like crafting a bunch of keys and storing them safely in a JWK Set.

II. GetAnyPrivateKeyWithKeyId — Grabbing a Key

When you need a key to sign something, this function grabs the first private key in your vault and gives it to you along with the Key ID. (For demo purposes, I’m picking the first key, but you can implement your own logic to fetch a specific key or even pick a random key from the set.) It’s like reaching into your vault, picking a key, and knowing exactly which one you grabbed.

III. GetPublicKeyBy — Handing Over the Public Key

If someone else needs to verify something you’ve signed, this function finds the matching public key by its Key ID and hands it over. Now they can verify the signature without touching your private key.

IV. GetPublicKeys — Sharing the Vault

Want to share your keys? This function pulls out all the public keys from your vault and makes them available for others, which is perfect for setting up a JWKS endpoint so people can access your public keys securely.

2. Jwt Manager – The Token Crafter 🎟️

Here, the IJwtManager interface outlines two main actions: generating tokens and verifying them. JwtManager implements these actions by relying on the IJwkManager to handle key management, keeping JWT creation and verification simple and clean.

I. GenerateToken — Crafting Your Token

Imagine you need a token with some custom claims. This function takes your claims and creates a JWT. It sets standard fields like issued_at and expiration_time, then signs the token using an RSA private key from the JwkManager. The signed token is then ready for use. It’s like sealing your message in a secure envelope, ready to be sent.

⚠️ Note: Be cautious not to include sensitive information in the JWT payload, as anyone with the token can decode it using tools like — jwt.io

II. VerifyTokenSignatureAndGetClaims — Verifying the Token

When someone receives your JWT and needs to verify it, this function helps. It first checks if the JWT’s signature is valid by using the public key from the JwkManager. If everything checks out, it extracts and returns the claims inside the token. It’s like someone checking if the seal on your envelope is authentic and then opening it to read the contents.

😎 Here’s the fun part: If anyone tries to change the payload, the signature validation won’t let it slide, keeping the token safe and sound.

3. Auth Service – The Bridge 🧩

Here, AuthService relies on JwtManager for creating tokens and verifying them, while JwkManager handles public keys. With this setup, you get a full-service authentication solution.

I. GenerateJwt — Creating the Token

When you need a JWT for a user, this function takes the user’s details, converts them to a map, and calls GenerateToken from the JwtManager. It’s like turning a user’s credentials into a sealed token, ready for use.

II. GetPublicKeys — Fetching the Keys

Need the public keys for your app to validate incoming tokens? This function gets them from the JwkManager. It’s like retrieving the master key to check if a JWT’s signature is authentic. This function provides the public keys that can be used to validate token authenticity, making it useful for any service that needs to verify the validity of a token.

III. VerifyToken — Verifying the Token

When someone presents a JWT for verification, this function goes to work. It checks if the token’s signature is valid and then extracts the user’s data from the claims. It’s like a security guard verifying the authenticity of an ID card and then checking the information inside. If everything checks out, the user’s details are returned.

4. CLI Menu with Cobra — Let’s Interact! 💬

This CLI is just for demo purposes. In real-world apps, you’d use these functions inside HTTP servers or APIs — not from the terminal.

I won’t go deep into what Cobra is, but in short: Cobra is a popular Go library for building CLI applications. It helps structure commands, flags, and interactive menus — perfect for quick testing like this.

🚀 Demo Time!

Time for some hands-on fun.

If you know how to run Go code, dive right in. If not, no stress — check out the README.md for setup help.

Once it’s up and running, you’ll see something like this:

JWT Authentication in Go Using JWKs

🦾 Why This Is Solid (and Secure)

  • Signed with RS256: All tokens are signed using RSA (RS256), making them tamper-proof.
  • Supports Key Rotation: Each key has a unique kid (key ID), so you can rotate keys easily without breaking old tokens.
  • Public Key Sharing Ready: The system can expose public keys in a format like /jwks.json, so others can verify tokens securely.
  • Token Expiry Set: Each token expires in 24 hours, limiting risk if it ever leaks.
  • In-Memory Keys (for demo): Keys are generated in memory.
    ⚠️ For real-world use, store and rotate keys securely using tools like Vault or AWS KMS.
  • Modular Design: Everything is split into clean layers — JWT logic, key management, and auth services.

💡 Final Thoughts

This project provides a clean, modular JWT system backed by JWK and a simple, user-friendly CLI. It’s a solid foundation for building a complete authentication microservice.

Whether you’re diving into distributed systems or just looking to get a deeper understanding of JWTs, this pattern is a great place to start. Give it a shot and see how it works for you!

✌️ Let’s Talk Code & More!

Want to chat more about JWTs, microservices, or just life in general? I’m always up for a chat. Let’s connect on LinkedIn and see what we can build next! 🤖🚀

--

--

TechVerito
TechVerito

Published in TechVerito

All about Technology, Software Craftsmanship, Agile

No responses yet