Building a RESTful API (Representational State Transfer Application Program Interface) is a popular way to create web services due to its scalability and statelessness. This article will guide you on creating a simple REST API using Node.js and OAuth 2.0, a standard for authorization. OAuth 2.0 allows users to grant third-party access to their web resources without sharing their passwords.
Our journey will include creating the REST API, implementing OAuth 2.0 for secure access, and testing our API.
1. Introduction to REST APIs and OAuth 2.0
REST APIs operate by sending HTTP requests to manipulate data (CRUD operations), which maps nicely to our Create, Read, Update, and Delete operations. OAuth 2.0 is an authorization framework enabling third-party applications to obtain limited access to an HTTP service.
2. Installing the Required Tools
Before we start, we need to install Node.js and npm (Node Package Manager).
Also, install Express.js, a minimalist web framework for Node.js. To do this, open your terminal and run the following command:
npm install express
We'll also use the express-oauth-server
package for OAuth 2.0 authentication and body-parser
to handle incoming request bodies:
3. Creating a Simple REST API
Now that we have our tools, we can start creating a simple REST API. We will create a simple in-memory store to hold our data.
const express = require('express');
const app = express();
let store = {};
app.use(express.json());
// Create data
app.post('/data', (req, res) => {
const { id, data } = req.body;
if (store[id]) {
return res.status(409).json({ message: 'Data with that ID already exists.' });
}
store[id] = data;
return res.status(201).json({ message: 'Data created.' });
});
// Read data
app.get('/data/:id', (req, res) => {
const data = store[req.params.id];
if (!data) {
return res.status(404).json({ message: 'Data not found.' });
}
return res.json({ data });
});
// Update data
app.put('/data/:id', (req, res) => {
const { data } = req.body;
if (!store[req.params.id]) {
return res.status(404).json({ message: 'Data not found.' });
}
store[req.params.id] = data;
return res.json({ message: 'Data updated.' });
});
// Delete data
app.delete('/data/:id', (req, res) => {
if (!store[req.params.id]) {
return res.status(404).json({ message: 'Data not found.' });
}
delete store[req.params.id];
return res.json({ message: 'Data deleted.' });
});
app.listen(3000, () => console.log('Server running on http://localhost:3000'));
We now have a simple REST API that supports CRUD operations.
4. Implementing OAuth 2.0
OAuth 2.0 is a standard for authorization that allows us to share specific data with an application while keeping our usernames and passwords private.
To implement OAuth 2.0, we will use the express-oauth-server
package. This package requires implementing several methods, including getAccessToken
, getClient
, saveToken
, getUser
, and `saveAuthorizationCode
.
4.1 Setting Up OAuth 2.0 Server
First, we will set up our OAuth 2.0 server:
const bodyParser = require('body-parser');
const OAuthServer = require('express-oauth-server');
app.oauth = new OAuthServer({
model: {}, // our model object
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
Here, we created a new OAuth 2.0 server and attached it to our Express app
object. We also told the server to use bodyParser
to handle incoming request bodies.
4.2 Implementing the OAuth 2.0 Model
Next, we need to implement our model. This is an object with methods that the OAuth 2.0 server uses to store and retrieve data.
const model = {
getAccessToken: async (bearerToken) => {
// get access token from storage
},
getClient: async (clientId, clientSecret) => {
// get client from storage
},
saveToken: async (token, client, user) => {
// save token in storage
},
getUser: async (username, password) => {
// get user from storage
},
saveAuthorizationCode: async (code, client, user) => {
// save auth code in storage
},
};
app.oauth = new OAuthServer({
model,
});
In this code, we added several placeholder methods to our model. Each of these methods would interface with your user database (for real applications, this could be a MongoDB, PostgreSQL, etc.).
4.3 Protecting Routes with OAuth 2.0
With our OAuth 2.0 server set up, we can now protect our routes. We will use the authenticate
middleware provided by express-oauth-server
:
app.post('/data', app.oauth.authenticate(), (req, res) => {
// handle request
});
app.get('/data/:id', app.oauth.authenticate(), (req, res) => {
// handle request
});
app.put('/data/:id', app.oauth.authenticate(), (req, res) => {
// handle request
});
app.delete('/data/:id', app.oauth.authenticate(), (req, res) => {
// handle request
});
Here, we added app.oauth.authenticate()
as a middleware to our routes. This function verifies that a valid access token is included in the request.
5. Testing Your REST API with OAuth 2.0
Finally, we need to test our API. There are several tools available for testing APIs, like Postman or Curl. However, for this guide, we will use a simple fetch
call.
fetch('http://localhost:3000/data/1', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
},
body: JSON.stringify({ data: 'My data' }),
})
.then(res => res.json())
.then(json => console.log(json));
Replace YOUR_ACCESS_TOKEN
with the actual access token. If everything works correctly, this should create a new data item and print the response to the console.
6. Conclusion
In this guide, we learned how to build a simple REST API with Node.js, and secure it using OAuth 2.0. This included setting up a basic Express app, creating routes to handle CRUD operations, setting up an OAuth 2.0 server, protecting our routes, and testing our API.