5 min read · Mar 18, 2023
JWTs (JSON Web Tokens) are widely used for securing web applications and APIs. They consist of a header, a payload, and a signature, which are base64-encoded and separated by dots. JWTs are signed using a secret key or a private key, and can be verified using a corresponding public key. In this article, we will explore how to create and verify signed JWTs using npm Jose, which is a JavaScript library for working with JSON Web Encryption (JWE) and JSON Web Signature (JWS). We will cover four main topics: adding required imports, creating a secret key of type KeyObject, signing the JWT, and verifying the JWT. By the end of this article, you will have a good understanding of how to create and verify signed JWTs using npm Jose.
Add Required imports
const { createSecretKey } = require('crypto');
// library for signing jwt
const { SignJWT } = require('jose-node-cjs-runtime/jwt/sign');
// library for verifying jwt
const { jwtVerify } = require('jose-node-cjs-runtime/jwt/verify');
The first line of code imports a library called crypto
, which is a built-in Node.js library for cryptographic operations. Specifically, it imports the createSecretKey
function, which generates a symmetric key that can be used for signing and verifying JWTs.
The second line of code imports a library called jose-node-cjs-runtime/jwt/sign
, which provides a SignJWT
class for creating and signing JWTs. This library uses the JSON Web Signature (JWS) specification to create a signature for the JWT using the previously generated symmetric key.
The third line of code imports a library called jose-node-cjs-runtime/jwt/verify
, which provides a jwtVerify
function for verifying the JWT's signature. This function uses the same symmetric key that was used to sign the JWT to ensure that the signature is valid.
In summary, these libraries provide the tools necessary to create a secret key, sign a JWT with that key, and verify the signature of a JWT using the same key.
Create Secret key of type KeyObject
const secretKey = createSecretKey(process.env.JWT_SECRET, 'utf-8');
The code creates a secret key using the createSecretKey
function from the crypto
library that was imported earlier. The createSecretKey
function takes two arguments: the first argument is a string representing the secret used to generate the key, and the second argument is the encoding format of the secret string (in this case, utf-8
). The secret key is then assigned to a constant variable called secretKey
.
In other words, this code generates a secret key for use in signing and verifying JWTs using the value stored in the JWT_SECRET
environment variable. The utf-8
encoding format is used to ensure that the secret is correctly represented as a sequence of bytes.
Sign the JWT
(async () => {
const token = await new SignJWT({
id: '12345'
}) // details to encode in the token
.setProtectedHeader({
alg: 'HS256'
}) // algorithm
.setIssuedAt()
.setIssuer(process.env.JWT_ISSUER) // issuer
.setAudience(process.env.JWT_AUDIENCE) // audience
.setExpirationTime(process.env.JWT_EXPIRATION_TIME) // token expiration time, e.g., "1 day"
.sign(secretKey); // secretKey generated from previous step
console.log(token); // log token to console
})();
This code defines an asynchronous arrow function that takes no arguments and is immediately executed using an IIFE (Immediately Invoked Function Expression). The purpose of this function is to create and sign a JWT with a specific set of claims and log it to the console.
First, a new SignJWT
object is created with an ID of '12345' as the payload to encode in the token. Then, several methods are called on this object to set the protected header (including the algorithm to use), the issuer and audience fields, the issued at timestamp, and the expiration time of the token.
Finally, the sign()
method is called on the SignJWT
object with the secretKey
that was generated earlier using createSecretKey()
. This method signs the JWT using the JSON Web Signature (JWS) specification and returns the signed token, which is then logged to the console using console.log()
.
In summary, this code creates a JWT with a specific set of claims, signs it using the secret key generated earlier, and logs the signed token to the console. This JWT can be used to authenticate and authorize access to a web application or API.
Verify the JWT
(async () => {
// extract token from request
const token = req.header('Authorization').replace('Bearer ', '');
try {
// verify token
const { payload, protectedHeader } = await jwtVerify(token, secretKey, {
issuer: process.env.JWT_ISSUER, // issuer
audience: process.env.JWT_AUDIENCE, // audience
});
// log values to console
console.log(payload);
console.log(protectedHeader);
} catch (e) {
// token verification failed
console.log("Token is invalid");
}
})();
This code defines an asynchronous arrow function that takes no arguments and is immediately executed using an IIFE (Immediately Invoked Function Expression). The purpose of this function is to verify a JWT that is extracted from a request header and log the payload and protected header of the JWT to the console.
First, the function extracts the JWT from the Authorization
header of the request and removes the Bearer
prefix using the replace()
method. Then, the jwtVerify
function from the jose-node-cjs-runtime/jwt/verify
library that was imported earlier is called with three arguments: the JWT to be verified, the secret key that was generated using createSecretKey()
, and an object containing the issuer and audience fields of the JWT.
If the JWT is successfully verified, the payload
and protectedHeader
objects are logged to the console. The payload
object contains the data that was originally encoded in the JWT, while the protectedHeader
object contains information about the algorithm used to sign the JWT, among other things. If the verification fails, the message "Token is invalid" is logged to the console instead.
In summary, this code verifies a JWT using the secret key generated earlier and logs its payload and protected header to the console if the verification succeeds.
In conclusion, generating and verifying JSON Web Tokens (JWTs) is an important aspect of building secure web applications and APIs. In this article, we learned how to use the npm Jose library to create a signed JWT and verify it using a secret key. We covered four main topics: adding required imports, creating a secret key of type KeyObject
, signing the JWT, and verifying the JWT. By following the code examples and explanations provided in this article, you should now have a good understanding of how to generate and verify JWTs using npm Jose in your own projects. Remember to always keep your secret key secure and to follow best practices when handling JWTs to ensure the security and integrity of your application.