How to Create a Secure API with OAuth and JWT in Express.js
In today's interconnected world, building secure APIs is a fundamental requirement for any web application. As developers, we need to ensure that sensitive user data is protected from unauthorized access. One of the best ways to achieve this is by implementing OAuth 2.0 for authorization and using JSON Web Tokens (JWT) for authentication. In this article, we will explore how to create a secure API using OAuth and JWT in Express.js, providing step-by-step instructions and code examples to guide you through the process.
What is OAuth and JWT?
Understanding OAuth
OAuth (Open Authorization) is an open standard for access delegation commonly used as a way to grant websites or applications limited access to user information without exposing passwords. It allows users to authorize third-party applications to access their data stored with another service.
What is JWT?
JSON Web Token (JWT) is a compact and self-contained way for securely transmitting information between parties as a JSON object. The information can be verified and trusted because it is digitally signed. JWTs can be encrypted for added security, ensuring that data remains confidential.
Use Cases for OAuth and JWT
- Single Sign-On (SSO): Users can log in once and gain access to multiple applications without needing to log in again.
- Third-Party Applications: Allowing users to grant access to their data on one platform to another application (e.g., logging in with Google or Facebook).
- Microservices Communication: Securely sharing user information between microservices without needing to handle sensitive credentials.
Setting Up Your Express.js Environment
Prerequisites
Before we dive into coding, ensure you have the following:
- Node.js installed on your machine.
- A basic understanding of JavaScript and Express.js.
- Familiarity with RESTful APIs.
Creating a New Express Project
- Initialize a new Node.js project:
bash
mkdir secure-api
cd secure-api
npm init -y
- Install the necessary dependencies:
bash
npm install express jsonwebtoken dotenv body-parser cors
- Create the necessary files:
bash
touch server.js .env
Configuring Your Environment Variables
Open the .env
file and add the following configuration:
PORT=5000
JWT_SECRET=your_jwt_secret_key
Replace your_jwt_secret_key
with a strong secret key of your choice.
Building the Express Server
Step 1: Set Up Basic Express Server
Open server.js
and set up a simple Express server:
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const jwt = require('jsonwebtoken');
const app = express();
app.use(cors());
app.use(bodyParser.json());
const PORT = process.env.PORT || 5000;
// Sample route for testing
app.get('/', (req, res) => {
res.send('Welcome to the Secure API!');
});
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
Step 2: Implementing User Registration and Login
Create endpoints for user registration and login. For simplicity, we'll use an in-memory array to store users.
let users = []; // This will hold user data temporarily
app.post('/register', (req, res) => {
const { username, password } = req.body;
const user = { username, password }; // In a real app, use hashed passwords
users.push(user);
res.status(201).send('User registered!');
});
app.post('/login', (req, res) => {
const { username, password } = req.body;
const user = users.find(u => u.username === username && u.password === password);
if (user) {
const token = jwt.sign({ username }, process.env.JWT_SECRET, { expiresIn: '1h' });
res.json({ token });
} else {
res.status(401).send('Invalid credentials');
}
});
Step 3: Protecting Routes with JWT Middleware
Now, we need middleware to protect our routes using JWT:
function authenticateToken(req, res, next) {
const token = req.headers['authorization'];
if (!token) return res.sendStatus(401);
jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
if (err) return res.sendStatus(403);
req.user = user;
next();
});
}
Step 4: Creating Protected Routes
Add a protected route that only authenticated users can access:
app.get('/protected', authenticateToken, (req, res) => {
res.send(`Hello ${req.user.username}, you have access to this protected route.`);
});
Testing the API
To test your API, you can use tools like Postman or cURL:
- Register a user:
bash
curl -X POST http://localhost:5000/register -H "Content-Type: application/json" -d '{"username": "testuser", "password": "testpass"}'
- Login to receive a token:
bash
curl -X POST http://localhost:5000/login -H "Content-Type: application/json" -d '{"username": "testuser", "password": "testpass"}'
- Access the protected route:
Replace TOKEN
with the JWT received from the login response.
bash
curl -X GET http://localhost:5000/protected -H "Authorization: TOKEN"
Conclusion
Creating a secure API with OAuth and JWT in Express.js is a powerful way to protect sensitive user data. By following the steps outlined in this article, you can implement secure user authentication and authorization in your applications. Always remember to use best practices, such as hashing passwords and validating user inputs, to enhance the security of your API further.
With this knowledge, you are now equipped to build secure APIs that can handle user authentication and authorization effectively. Happy coding!