JSON Web Token In Nutshell

JSON Web Token In Nutshell

What is JWT?

JSON Web Code (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way to securely transmit information between parties as JSON objects. This information can be verified and trusted as it contains a digital signature. JWTs can be signed with a secret algorithm (with the HMAC algorithm) or a public/private key using RSA encryption.

How is it structured?

  • JWT is a combination (with a dot “.”) of a Base64 encoded JSON Object Header, a Base64 encoded JSON Payload Object, and a Base64 encoded URI Signature.
<base64-encoded header>.<base64-encoded payload>.<base64-encoded signature>

Headers

  • The header consists of two main parts: the token type (default is JWT - This indicates that this is a JWT Token) and the algorithm used for the encryption (HMAC SHA256 - HS256 or RSA).
{
  "alg": "HS256",
  "typ": "JWT"
}

Payloads

  • The payload contains claims. Claims are expressions about an entity (such as a user) and some auxiliary metadata. There are 3 common types of claims in Payload: reserved, public and private claims.

    • Reserved Claims: Here are some predefined metadata, some of which are required, others should be followed for valid and informative JWT: iss (issuer), iat (issued at time), exp ( expiration time), sub (subject), aud (audience), jti (Unique Identifier for JWT, Can be used to prevent the JWT from being replayed. This is helpful for a one-time use token), etc.
  • Public Claims: These claims are optionally defined by us, to contain the information we want to transmit. Theoretically, it is enough for the token creator and the token recipient to understand each other. But to avoid collisions, they must be defined in the IANA JSON Web Token Registry or the URI containing the collision-resistant namespace.

  • Private Claims: It is a self-defined claim, it is created to share information between two parties that have previously agreed.

Signature

A signature in JWT is a string encrypted by the header, payload, and a secret string. The signature is used to verify that the message has not been changed during execution. In the case of a token signed with a private key, it can also verify that the sender of the JWT is confirmed.

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

How to generate JWT using Node.js?

npm install jsonwebtoken
  • Create an index.js file and update these codes into your file.
import jwt from 'jsonwebtoken';

const generateJwtToken = ({ ...args }) => {
    const token = jwt.sign({ args }, 'this_is_very_secret', {
      issuer: 'node:app',
      subject: 'test@sample.com',
      audience: 'node:client',
      jwtid: 'userId',
      expiresIn: '24h',
    });
    return token;
};

const newToken = generateJwtToken({
    userId: '123',
    email: 'test@example.com',
});

console.log(newToken) // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcmdzIjp7InVzZXJJZCI6IjEyMyIsImVtYWlsIjoidGVzdEBleGFtcGxlLmNvbSJ9LCJpYXQiOjE2OTI4ODk0OTUsImV4cCI6MTY5Mjk3NTg5NSwiYXVkIjoibm9kZTpjbGllbnQiLCJpc3MiOiJub2RlOmFwcCIsInN1YiI6InRlc3RAc2FtcGxlLmNvbSIsImp0aSI6InVzZXJJZCJ9.qzDzMOpnRhl8PzKFBL2VEqyPUUMgJ1Gam6ayVGeuwlw

// Decode the above token, then we've got this information
{
  "args": {
    "userId": "123",
    "email": "test@example.com"
  },
  "iat": 1692889495,
  "exp": 1692975895,
  "aud": "node:client",
  "iss": "node:app",
  "sub": "test@sample.com",
  "jti": "userId"
}
  • To verify your token is valid, using jwt.verify function to do that.
const verifyToken = (token) => {
  if (token) {
    const verifiedToken = jwt.verify(token, 'this_is_very_secret');
    return verifiedToken;
  }
};

console.log(verifyToken(newToken)); 

// Info from verifyToken function 
{
  args: { userId: '123', email: 'test@example.com' },
  iat: 1692890465,
  exp: 1692976865,
  aud: 'node:client',
  iss: 'node:app',
  sub: 'test@sample.com',
  jti: 'userId'
}

What is it used for?

Authentication: In the most common scenario, after a user logs in, each subsequent request is accompanied by a JWT token string. This token string allows the user to access authorized paths, services, and resources. Single Sign On also utilizes JWT extensively, due to its compact size, which enables it to be included in requests and used across different domains and systems.

Information Exchange: JSON Web Token is an efficient and secure way to exchange information between multiple applications. Since the JWT must be signed with a public/private key pair, you can be sure that the sender is who they say they are (making it difficult to impersonate with JWT). Additionally, the signature is calculated based on the header and payload content, so you can authenticate that the content is original, unedited, or tampered with. However, it's important to note that because the structure of JWT is simple, it can be easily decoded. Therefore, it's not recommended to use JWT to transfer sensitive information.

JWT in Authentication

In authentication, when the user logs in successfully (Browser will post username and password to the Server), the Server will return a JWT string to the Browser, and this JWT Token needs to be saved in the User's Browser (usually LocalStorage or Cookies), instead of the traditional way of creating a session on the Server and returning a Cookie.

Whenever the User wants to access the Protected Route (which only the logged in User is allowed), the Browser sends this JWT token in the Header Authorization, Bearer schema of the outgoing request.

Authorization: Bearer <token>

This is how stateless (stateless) authentication works, the user's state is not stored in the server's memory but is encapsulated in the JWT. The server will check this JWT Token is valid or not (Because JWT is self-contained, all the information needed to check the JWT is already contained in the JWT Token).

Because of its stateless nature, we no longer have to worry about which domains are used for your API, like no more trouble with CORS (Cross-Origin Resource Sharing) because it doesn't use cookies.

References

JWT.io