In this tutorial, we'll explore how to secure your RESTful API using JWT (JSON Web Tokens). JWT is a self-contained method for securely transmitting information between parties. It's a popular choice for handling user authentication and authorization in web applications.
By the end of this tutorial, you'll understand the basics of JWT, how to implement JWT authentication in an Express.js application, and how to protect your API routes using JWT.
Prerequisites for this tutorial include a basic understanding of JavaScript and familiarity with Node.js and Express.js.
JWTs are encoded JSON objects, which are digitally signed. They can be verified and trusted because they are signed. JWTs can be encrypted to also provide secrecy between parties. JWTs are used for authentication and secure information exchange.
JWTs are composed of three parts: header, payload, and signature. They are separated by periods (.) and look like this: xxxx.yyyy.zzzz
.
We'll use the jsonwebtoken
package to handle JWT in our Express.js app. Install it using npm:
npm install jsonwebtoken
Here's how you can create a JWT in an Express.js application:
const jwt = require('jsonwebtoken');
const user = { id: 1, username: 'test' };
const accessToken = jwt.sign(user, 'secretKey', { expiresIn: '1h' });
console.log(accessToken);
In this example, jwt.sign()
creates a new JWT. The first parameter is the payload (user object), the second is a secret key, and the third is an options object where we specify the token's lifetime.
To verify a JWT, we use jwt.verify()
:
const data = jwt.verify(accessToken, 'secretKey');
console.log(data);
If the token is valid, jwt.verify()
will return the payload.
In this tutorial, we covered the basics of JWT and how to implement JWT authentication in an Express.js application. We learned how to create and verify JWTs and how to secure API routes using JWT.
To continue learning about JWT and Express.js, consider exploring how to handle errors when verifying tokens and how to refresh tokens when they expire.
Create a JWT with a payload containing an object { id: 2, username: 'test2' }
. Set the token's lifetime to 2 hours.
Verify the token you created in the first exercise. What's the output?
Create an Express.js application with a single protected API route. The route should return a message "Hello, [username]!" where [username] is the username from the JWT payload. Use the JWT from the first exercise to access this route.
Solutions
const user = { id: 2, username: 'test2' };
const accessToken = jwt.sign(user, 'secretKey', { expiresIn: '2h' });
console.log(accessToken);
const data = jwt.verify(accessToken, 'secretKey');
console.log(data);
The output will be the payload of the token: { id: 2, username: 'test2', iat: [timestamp], exp: [timestamp] }
.
const express = require('express');
const app = express();
app.get('/protected', (req, res) => {
const token = req.headers['authorization'];
if (!token) return res.status(401).send('Access Denied');
try {
const data = jwt.verify(token, 'secretKey');
res.send(`Hello, ${data.username}!`);
} catch {
res.status(401).send('Invalid Token');
}
});
app.listen(3000);
In this solution, we first check if the request contains a token. If not, we return a 401 status. If a token is present, we attempt to verify it. If verification is successful, we send a personalized message to the user. Otherwise, we return a 401 status.