Understanding and Creating JWTs

Written by
Everett Merrill and Alex Stewart
13 mins
Sep 12, 2025
Subscribe for more insights
Thank you for your interest in the syllabus.

We'll be in touch soon with more information!

In the meantime, if you have any questions, don’t hesitate to reach out to our team.

Oops! Something went wrong while submitting the form.

TLDR - Understanding and Creating JWTs

  • JWT (JSON Web Token): a compact, stateless way to handle authentication.
  • JWTs replace traditional session-based authentication for scalability.
  • Anatomy of JWT: Header (algorithm), Payload (claims), Signature (verification).
  • Pros: scalable, stateless, cross-service portability.
  • Cons: harder to revoke early, requires careful handling.
  • Tutorial: Create JWTs in Express/Node.js and test in Postman.
  • Refresh tokens extend session security by issuing new access tokens.
  • JWT stands for JSON Web Token, though most people just pronounce it ‘jot.’

    JWTs offer a fantastic alternative to standard session-based authentication cookie methods by providing all the information an application needs to authenticate and authorize a user’s session in a handy Base64 encoded stateless token that is stored completely on the client side.

    In this article, we’re going to break down:

    • Authentication vs. Authorization
    • Session- based Authentication and it’s pros and cons
    • Why JWT- based Authentication is a great alternative to Session-based
    • The anatomy of JWTs and how they’re encoded
    • How to create your own JWTs in ExpressJS and test them out in Postman
    • Refresh tokens

    What is a JWT?

    To put it simply, JWTs are compact, stateless tokens used to authenticate and authorize a user’s requests in an application or website.

    Once encoded and signed, a JWT has three parts, each separated by a period: 

    1. The Header contains an algorithm designated to encode and decode the token.
    2. The Payload  is composed of key/value pairs called “claims” that contain all the auth information (ie user ID, roles/permissions, expiration, etc.).
    3. The Signature is the way the server verifies that the user has not tampered with the token, if the signature changes upon request, the server rejects the request and the sender is not authorized.

    *Note: While JWTs are Bas64 encoded, they can be decoded. A JWT’s signature prevents tampering but does not hide its contents. Do not put secret information in the payload or header elements of a JWT (such as a password) unless it is encrypted.

    base64 Encoded JWT

     
    Some Pros to JWT Tokens include:
     

    • Stateless, fast, portable, stored on client’s browser.
    • Easy to scale across multiple servers and microservices.

    Some Cons to JWT Tokens include: 

    • Once a token has been issued, it’s difficult to stop the session prior to its expiration.
    • Requires careful storage and handling.

    Authentication vs. Authorization

    Before diving into JWTs, let’s clear up a common mix-up:

    Authentication answers “Who are you?”. The server uses your credentials to prove that you are, in fact, who you say you are. Like logging in with the correct username and password.

    Authorization answers “What are you allowed to do?”. Now that you’re logged in, which resources do you actually have access to? For example, are you just a user, or are you allowed admin access?

    Session-Based Authentication

    Session-Based Authetication Flow

    Session-based authentication is fine for small-scale applications but becomes more and more complex with multiple servers or microservices. Since session data is stored on the server, every server needs access to a single-source of truth in order to validate active sessions. Without the servers being in sync, discrepancies can occur, which leads to unrecognized sessions and failed user requests. 

    Session based storage solves this problem by allowing us to save sessions to a database or a centralized session store which holds the session information in one place so all the servers can access it. However, this adds a layer of complexity because more databases = more overhead.

    Centralized Session Store

    With all this in mind, JWTs were created to mitigate many of the challenges that come with scaling large applications in a session based cookie system.

    JWT-Based Authentication Flow

    Now that we understand Session-Based Authentication, let’s take a look at how JWTs streamline session management by taking a look at the way a JWT Authentication Flow works:

    JWT Authentication Flow

    Anatomy of JWTs

    A JWT is a string with three sections separated by periods (.):

    Header

    This contains metadata about the token (ie: type = JWT, algorithm = HS256 or RS256).

    JWT Anatomy

    Payload

    This is made up of key/value pairs called “claims” which contain metadata about the user or the token itself like user ID, role, expiration, and any other data you may want the JWT to hold on to. Claims can be custom (private), registered, or public.

    There are three types of Payload claims that are important to know: Registered, Public, and Private. If a system consumes multiple JWTs from multiple companies and those companies use the same claim key name with different meanings, it causes misinterpretation known as collision. For instance if two companies use “role” as a payload claim, and one company means “admin” or “user” while the other company means a person’s “job title”, the consuming system could misapply authorization logic. 

    In an effort to avoid this wherever possible, the Internet Assigned Numbers Authority (IANA) maintains a registry of standard claim names. Some examples of Registered Claims include iss (issuer), sub (subject), and exp (expiration time). You can view the full list of registered claims at iana.org

    Public claims are custom claims defined in a JWT payload with the intention of sharing across multiple systems or microservices, usually within the same organization. For instance, if a massive conglomerate owns multiple major social media sites with users who register to one or the other or both, this information needs to be sent in the payload. The claim should have a unique prefix tied to a namespace to avoid collision. For instance, a Public Claim in a JWT payload should look like this: “https://mysocialmediasite.com/role”: “admin”.

    Private Claims are also custom claims, but they are not meant to be used across many systems, they are meant for internal use within a company. For example, developers for an e-commerce platform might use “cartID”: “94b12fae-4c67-4f59-b4gh” to track a customer’s active shopping cart between frontend and backend services. There’s no need to register or namespace it, because this claim is only meaningful within the system and will not be subject to collision.

    JWT Anatomy

    Signature

    This is what makes JWTs so fantastic! It’s created by hashing the header and payload with a secret or private key. If anyone tampers with the data on the JWT, the signature no longer matches, and the session automatically expires which will require the user to log in again.

    • The signature makes sure the JWT hasn’t been tampered with.
    • It’s created by combining the header, payload, and a secret or private key through the algorithm specified in the header (like HS256 or RS256).
    • The result is base64 encoded and makes up the third part of the JWT.
    • If anyone alters the header or payload, the signature will no longer match, and the JWT becomes invalid.
    • The secret or private key should be kept safe in either a .env file during development or a secure environment variable provided by production infrastructure (like AWS Secrets Manager). You can create a random secret or private key by using the “crypto” library and invoking crypto.randomBytes(32).toString('hex'). This will give you a random, 64 character string.
    JWT Anatomy - Signature

    Common Use Cases for JWTs

    Single Sign-On (SSO): A user can authenticate just once and then use that same token to access multiple independent applications or services. That’s why JWTs are a common choice in OAuth2 and OpenID Connect systems. Like when you sign into an application through your Google account!

    API Authentication: JWTs are often used as Bearer tokens in API requests which means microservices (like adding items to a cart) or client applications (like those in your browser) to prove their identity without having to maintain server-side sessions. For example, on your bank app, when you click to see your account balance, the JWT can be sent as a Bearer token in the Authorization header of the request for that page and data. That way, if the JWT is valid and hasn’t expired, you can view your balance. Otherwise, the app will require you to sign back in.

    Note: If you’re having a hard time picturing where the Authorization header is in an HTTP request, check out our article on the JavaScript fetch API.

    Mobile Apps & SPAs: In browser based applications, cookies are stored on the browser, in mobile apps they’re not (unless the app uses WebView which does have its own cookie storage). That makes cookie-based sessions difficult to manage. Instead, the JWT is usually stored in secure storage and gets sent as a Bearer token in every HTTP request that requires authentication.

    Create Your Own JWTs

    JWTs support a variety of use cases, including login authorization and secure API communication. For the purposes of this tutorial, the focus will be limited to the login flow using Express and Node.js, then we will test the setup with Postman.

    Testing your JWTs with Postman 

    Let’s test out this JWT flow in Postman:

    • Open a new request tab and set the method to POST.
    • Enter the URL of your login route, for example http://localhost:3000/login.
    • In the Body tab, select raw JSON and send your “user’s credentials” (in this case just a username since this tutorial won’t be handling authentication).
    • Send the request and look at the response in the body tab. Notice a message of “Logged in!”.
    JWT with Postman

    Click the “Cookies” tab to find the JWT we sent in our response! We will use this to access our “user profile” information (username and hairColor) in a moment.

    We can either copy from the Cookies tab in the response section as seen above, or from the cookies tab in our request section as seen below.

    Copy the JWT from the cookie.

    Our JWT, it will be sent with every request from the browser in the form of a cookie. But, remember not all apps send JWTs this way. Instead, we can send it as a Bearer token by adding it as an Authorization header. Now that we have our JWT copied, navigate to the Authorization tab. 

    JWT with Postman

    Now, paste it in as a Bearer token in the Authorization header. 

    Switch the request to ‘get’ and change the url to http://localhost:3000/profiles.

    JWT with Postman

    And now in the response body, we see our user’s profile information as sent from the server!

    Refresh tokens

    We couldn’t write an article about JWTs without mentioning refresh tokens. As we explained, you can configure the expiration for your JWT (access token). But, remember, if someone has access to your JWT, they can access your information on the server. This is where refresh tokens come in.

    Using one JWT as your access token for a long period of time is dangerous. Instead, you can also create a refresh token that will be used to get a new access token once the last access token has expired. Refresh tokens can last days, weeks or even months.

    But wait! Can’t someone steal your refresh token and continue to generate new access tokens as long as that refresh token is valid? Yes. That’s why refresh tokens are meant to live longer than regular access tokens, but not forever. They limit the window of opportunity for abuse. Each time a client uses a refresh token to get a new access token, your server should issue a new refresh token and invalidate the old one.


    Refresh tokens can be created the same way as any other JWT and stored centrally (in a database for example). Since they are used far less frequently than access tokens, it’s still a more efficient process than session-based management in terms of storage.

    Conclusion

    JWTs are one of the most widely used forms of authentication today. They are stateless and ensure quick access to scaled up, distributed systems, and applications with many microservices. JWTs are extremely efficient and scalable, but they are not a one-size fit all authentication fix. As with all technologies, it is important to consider your particular system’s design. Consideration should also extend to revocation strategies, claim design, and storage practices in order to strengthen your system’s design, because a poorly created JWT can easily make your application susceptible to attackers. With all these considerations in mind, a well crafted JWT might just be what you need to scale your application to the next level.

    FAQ’s

    How do I use JWT token authentication?

    You can send it with every request to a server, either as a Bearer token in the header or in an httpOnly cookie.

    Why use JWT instead of sessions?

    JWTs scale better across large, distributed systems and avoid centralized session stores. If an application uses several servers, instead of storing your session information in a database, they can use JWTs which are stored on the client and contain all the information needed for authorization.

    Is JWT an API token?

    Not exactly. API tokens are a string of characters you can include in your API request. In this case, the server would have a database of valid tokens. If your token matches one in the database, the request succeeds. JWT is a format often used for API tokens, but not all API tokens are JWTs.

    Does Base64 encoding protect JWT metadata?

    Base64 encoding can easily be decoded by anyone with access to the internet. For that reason, you should never add sensitive data to any part of your JWT.

    Can JWTs be revoked?

    JWTs can only be revoked if the token expires or the server registers that the signature has been tampered with in the process of verifying a user’s response. It is difficult to stop a JWT once it is in motion, so it is best practice to implement the use of refresh tokens and to keep expirations limited to minutes or at most a few hours. 

    What does JWT stand for?

    JWT stands for JSON Web Token.

    Find out how we cover AI/ML in our updated curriculum
    Get your Syllabus
    Special blog guest offer!

    Explore CS Prep further in our beginner-friendly program.

    Get 50% Off CS Prep
    Learning code on your own?

    Get more free resources and access to coding events every 2 weeks.

    Thank you for your interest in the syllabus.

    We'll be in touch soon with more information!

    In the meantime, if you have any questions, don’t hesitate to reach out to our team.

    Oops! Something went wrong while submitting the form.
    Want to learn more about advancing your career in tech?

    Connect with one of our graduates/recruiters.

    Schedule a Call

    Our graduates/recruiters work at:

    ABOUT THE AUTHOR

    Everett and Alex Stewart are proud Codesmith alumni who bring creativity and storytelling into the world of software development. Everett, a software engineer and content creator with a background in media production, transitioned into tech to combine problem solving with human-centered creativity. When Everett is not contemplating life near a large body of water, you can find him writing code, producing content, or jamming on guitar. Alex is a former professional actor turned developer. His passion lies in making tech fun and accessible through talks, tutorials, and blogs, drawing on his experience as a performer as well as with JavaScript, React, and Node/Express. Together, they are committed to creating technical content that resonates both technically and creatively.

    Related Articles

    Introduction to Recursion in JavaScript

    JavaScript
    Tutorial
    by
    Everett Merrill and Alex Stewart
    Nov 21, 2025
    |
    12 minutes

    What Is Coding? A Plain-English Guide With Real Examples

    Skills
    Tutorial
    by
    Alex Stewart
    Nov 7, 2025
    |
    10 minutes

    JavaScript From Zero: Step by Step Guideline

    JavaScript
    Tutorial
    by
    Alex Stewart
    Oct 13, 2025
    |
    7 minutes

    Start your journey to a coding career.

    Thank you for your interest in the syllabus.

    We'll be in touch soon with more information!

    In the meantime, if you have any questions, don’t hesitate to reach out to our team.

    Oops! Something went wrong while submitting the form.
    Want to learn more about advancing your career in tech?

    Connect with one of our recruiters to learn about their journeys.

    Schedule a Call

    Our graduates/recruiters work at: