JSON Web Tokens (JWTs)

JSON Web Tokens (JWTs)

Introduction

Amidst the diverse authentication methods available, JSON Web Tokens (JWTs) have emerged as a widely adopted choice, offering a lightweight, secure, and versatile approach to conveying user identity and authorisation information.

These self-contained tokens encapsulate sensitive data and facilitate seamless authentication between applications.

Delving into the World of JWTs: A Comprehensive Overview

JWTs, pronounced “jots,” are an open standard defined by RFC 7519 that utilises JSON objects to securely transmit authentication information.

These tokens are inherently stateless, meaning that the server does not need to store user session data after authentication. This simplifies the server-side architecture and enhances scalability.

The structure of a JWT comprises three distinct components:

  1. Header: The header specifies the token’s type, the cryptographic algorithm employed for signing or encryption (if applicable), and the encoding scheme.
  2. Payload: The payload carries the actual claims, which are statements about the user’s identity, authorisation levels, and other relevant information.
  3. Signature: The signature, generated using a secret key, ensures the integrity and authenticity of the token, preventing unauthorised tampering.

Harnessing the Power of JWTs: Benefits and Use Cases

JWTs offer a compelling set of advantages that make them a cornerstone of modern authentication:

  1. Compactness: They are lightweight and can be easily embedded in URLs, HTTP headers, or other data streams, optimising their transmission.
  2. Versatility: They can convey a wide range of claims, including user identification, authorisation levels, expiration timestamps, and more.
  3. Security: They can be signed or encrypted to protect their integrity and authenticity, safeguarding sensitive information from unauthorised access.
  4. Stateless Authentication: They are stateless, reducing server-side storage requirements and improving scalability.

JWTs find widespread applicability in various scenarios:

  1. API Authentication: JWTs are commonly used to authenticate API requests, enabling secure access to protected resources.
  2. Single Sign-On (SSO): JWTs facilitate seamless SSO experiences by allowing users to log in once and access multiple applications with a single authentication token.
  3. Microservices Architecture: JWTs simplify authentication between microservices, enabling decentralised authorisation and authorisation.

Signing JWTs: Ensuring Integrity and Authenticity

Signing a JWT involves applying a cryptographic hash function to the header and payload, combining them with a secret key. This generates a signature that is appended to the token and used to verify its authenticity.

Examples of Signing JWTs in C# and TypeScript

Here are examples of signing JWTs using the HMAC algorithm with SHA-256:

using System.Text.Json;
using System.Security.Cryptography;

string secretKey = "your_secret_key";

string payload =
    "{
        "userId": 123456,
        "username": "johndoe",
        "issuer": "example.com",
        "issuedAt": 1516768351,
        "jwtId": "unique_token_identifier"
    }";

byte[] signatureBytes = Encoding.UTF8.GetBytes(payload);
using (var signer = new HMACSHA256(Encoding.UTF8.GetBytes(secretKey)))
{
    var signature = Convert.ToBase64String(signer.ComputeHash(signatureBytes));
}

string token = $"{payload}.{signature}";
Console.WriteLine(token);

TypeScript Example:

import * as jwt from 'jsonwebtoken';

const secretKey = 'your_secret_key';

const payload: { userId: number; username: string; issuer: string; issuedAt: number; jwtId: string } = {
  userId: 123456,
  username: 'johndoe',
  issuer: 'example.com',
  issuedAt: Date.now(),
  jwtId: Math.random().toString(),
};

const token = jwt.sign(payload, secretKey);
console.log(token);

Conclusion

JSON Web Tokens (JWTs) have revolutionised the way in which information exchange and authentication are handled in modern web applications. Prior to their introduction, traditional methods such as session-based authentication were predominantly used. These methods involved storing user session information on the server, which could become cumbersome and inefficient, especially with the increasing scale of web applications.

JWTs, on the other hand, offer a stateless solution. They are compact, self-contained tokens that can securely transmit information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.

One of the main advantages of JWTs is their simplicity and ease of use across different domains. Because they are self-contained, they encapsulate all the necessary information about the user, eliminating the need to query the database more than once. This significantly reduces the load on the server and streamlines the authentication process.

Moreover, JWTs are versatile in terms of security and flexibility. They can be used in various scenarios, from simple authentication to complex OAuth flows. Their ability to be easily transmitted via URL, POST parameter, or inside an HTTP header further enhances their utility in different contexts, including cross-origin and cross-site requests.

In a world where security and efficient performance are paramount, JWTs stand out for their ability to balance these needs. They have become a fundamental component in modern web development, offering a robust and scalable method for managing authentication and information exchange. As web technologies continue to evolve, the role of JWTs is likely to grow even more significant, making them an indispensable tool for developers.

If you want to see what is in a JWT, there is a great decoder here: – https://jwt.io

I have also written about JWTs here: – Building a Secure Web API with C#.

Stephen

Hi, my name is Stephen Finchett. I have been a software engineer for over 30 years and worked on complex, business critical, multi-user systems for all of my career. For the last 15 years, I have been concentrating on web based solutions using the Microsoft Stack including ASP.Net, C#, TypeScript, SQL Server and running everything at scale within Kubernetes.