Jul 28, 2023

What is a Rest API?

A REST API is a standardized method allowing software systems to communicate over the internet. It allows different software applications to communicate with each other using standard HTTP methods. It's essential because it enables various software components to integrate smoothly, facilitates the scaling of software systems, and permits diverse devices, from phones to PCs, to utilize services. From a cybersecurity perspective, APIs can be likened to the doors of a software system. If these "doors" aren't properly secured, it opens opportunities for data breaches or malicious attacks. Therefore, it's crucial for security professionals to ensure these communication points are safeguarded.

Imagine a REST API as the front desk of a hospital. You're a doctor who needs a patient's records. Instead of rummaging through file cabinets yourself, you approach the front desk (the API). The desk personnel retrieve the correct records and hand them over, ensuring you get the right information for your patient.

Why is it useful? In a bustling hospital, numerous doctors and medical staff continuously need access to different patient records. They rely on the front desk, much like software relies on APIs, to efficiently and accurately fetch the required data.

For cybersecurity: Think about the importance of patient records staying confidential. If our "front desk" (API) isn’t careful, unauthorized personnel might view or even alter the records. This could lead to medical errors or privacy breaches. That's why it's crucial that our API (front desk) maintains strict security protocols, ensuring records are only handed over to authorized individuals and remain confidential.

To summarize, as modern applications increasingly rely on REST APIs for data exchange and functionality, understanding their workings and potential vulnerabilities becomes indispensable in cybersecurity. In this project, we'll be following Josh Madakor's tutorial on REST API.


What we'll learn

HTTP Request:

  • Definition: A message from a client (like a web browser) to a server, requesting action on a resource. Defined by methods like GET, POST, PUT, DELETE.

  • Example: A nurse checking a patient's history sends an HTTP request to fetch that data.

Web Request:

  • Definition: Any request made over the web, including but not limited to HTTP. Can be via other protocols like FTP or WebSockets.

  • Example: A hospital system backing up X-rays might use an FTP-based web request.

Key Difference:

  • An HTTP request is specific to the HTTP protocol, mainly for web content.

  • A web request is a broader term, encompassing any internet-based request.

Importance: Knowing the difference ensures efficient communication within systems and helps maintain security, especially critical in settings like hospitals where data privacy is paramount.


  1. HTTP GET:

    • Description: Used to retrieve information from a resource.

    • Hospital Scenario: A nurse wants to view the medical history of a patient. They would use a GET request to "ask" the hospital's system for that specific patient's medical record.

  2. HTTP PUT:

    • Description: Used to update an existing resource or create a new one if it doesn't exist.

    • Hospital Scenario: A doctor completes a new diagnosis for a patient and wants to update the patient's file with this new information. The doctor would use a PUT request to either update the existing patient record or, in the case of a new patient, create a fresh record with the initial diagnosis.

  3. HTTP POST:

    • Description: Used to submit data to be processed to a specified resource, usually creating a new resource.

    • Hospital Scenario: A new patient is admitted to the hospital for the first time. The administrative staff would use a POST request to create a brand new medical record for this patient in the hospital's system.

  4. HTTP DELETE:

    • Description: Used to delete a specific resource.

    • Hospital Scenario: If a patient's records needed to be removed from the system for some reason, perhaps due to a data retention policy or a special request, the system administrator would use a DELETE request to remove that patient's file.

Why are they useful for a REST API project?

  • CRUD Operations: These methods provide the basic operations for any data-driven application: Create (POST), Read (GET), Update (PUT), and Delete (DELETE). They map directly to standard operations we'd want to perform on data.

  • State Manipulation: They allow clients to interact with resources on a server, whether that's retrieving data, updating data, creating new data, or deleting data.

  • Standardization: Since they are standardized methods, developers know what to expect when interacting with RESTful services. It simplifies integration and communication between systems.

Importance of Understanding:

  • Predictability: Knowing these methods helps developers anticipate how a RESTful API should behave. It brings uniformity in how software components interact.

  • Data Integrity: Understanding when to use POST vs PUT, for example, can ensure data is added or modified in the intended way, preserving the integrity and consistency of the database.

  • Security: Each method comes with its security considerations. For instance, unrestricted DELETE capabilities can be disastrous, while excessive GET requests without protection can lead to DDoS attacks. Being aware of these methods helps in implementing appropriate security measures.


Contents

  • Project Setup

  • Crafting the API Framework

  • Constructing a Mock Patient Database

  • Developing the 'Retrieve Patient Records' API Endpoint

  • Designing the 'Add New Patient' Endpoint

  • Creating the 'Modify Patient Phone Details' Endpoint

  • Implementing the 'Remove Patient and Their Records' Endpoint


What you'll need

Visual Studio Code

  • Visual Studio Code is a free editor supporting multiple programming languages like Python, Java, C++, and JavaScript, allowing seamless coding without changing tools.

Node.js

  • Node.js® is an open-source, cross-platform JavaScript runtime environment.

Postman

  • Postman is a platform for developing and utilizing APIs. It streamlines the API lifecycle and collaboration, enabling quicker and better API creation.


Project Setup

  • Create a new folder on your desktop called API

  • Launch VSCode and run as administrator

  • Select file > open folder > API

  • Select Terminal > New Terminal

  • In terminal type: npm init. NPM stands for node packet manager, INIT stands for initialize


  • Press Enter to select all the default settings and type yes


  • Type: npm install express


  • Type: npm install body-parser. Used to parse the body of API requests


  • Type:
    Set-ExecutionPolicy Unrestricted
    npm install nodemon -g


  • Select API > New File > Name it index.js


Crafting the API Framework

This section sets up the basic requirements and structure for your Express-based API:

const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.json());

app.listen(3000);


Constructing a Mock Patient Database

Here, you're creating two in-memory objects (patients and records) to represent a simple mock database of patients and their medical records:

let patients = new Object();
patients["999991234"] = ["Jensen", "Watkins", "425-555-1234"]
patients["999995678"] = ["Patrick", "Bartholomew", "425-555-5678"]

let records = new Object();
records["999991234"] = "Status: Healthy"
records["999995678"] = "Status: Slight Cold"


Developing the 'Retrieve Patient Records' API Endpoint

This endpoint (GET /records) lets you fetch the medical records of a patient based on certain headers provided:

app.get("/records", (req, res) => {
    if (records[req.headers.ssn] === undefined) {
        res.status(404).send({"msg":"Patient not found."})
        return;
    }
    
    if (req.headers.firstname == patients[req.headers.ssn][0] && req.headers.lastname == patients[req.headers.ssn][1]) {
        if (req.body.reasonforvisit === "medicalrecords") {
            res.status(200).send(records[req.headers.ssn]);
            return;
        }
        else {
            res.status(501).send({"msg":"Unable to complete request at this time: " + req.body.reasonforvisit})
            return;
        }
    }
    else {
        res.status(401).send({"msg":"First or Last didn't match SSN."})
        return;
    }

    res.status(200).send({"msg": "HTTP GET - SUCCESS!"});
});


Designing the 'Add New Patient' Endpoint

This endpoint (POST /) allows you to add a new patient:

app.post("/", (req, res) => {
    patients[req.headers.ssn] = [req.headers.firstname, req.headers.lastname, req.headers.phone]
    res.status(200).send(patients)
});


Creating the 'Modify Patient Phone Details' Endpoint

This endpoint (PUT /) lets you update the phone number for an existing patient:

app.put("/", (req, res) => {
    if (records[req.headers.ssn] === undefined) {
        res.status(404).send({"msg":"Patient not found."})
        return;
    }

    if (req.headers.firstname == patients[req.headers.ssn][0] && req.headers.lastname == patients[req.headers.ssn][1]) {
        patients[req.headers.ssn] = [req.headers.firstname, req.headers.lastname, req.body.phone];
        res.status(202).send(patients[req.headers.ssn]);
        return;
    }
    else {
        res.status(401).send({"msg":"First or Last didn't match SSN. (Trying to update Ph #)"})
        return;
    }
});


Implementing the 'Remove Patient and Their Records' Endpoint

This endpoint (DELETE /) allows you to remove a patient and their corresponding medical records:

app.delete("/", (req, res) => {
    if (records[req.headers.ssn] === undefined) {
        res.status(404).send({"msg":"Patient not found."})
        return;
    }
    
    if (req.headers.firstname == patients[req.headers.ssn][0] && req.headers.lastname == patients[req.headers.ssn][1]) {
        delete patients[req.headers.ssn]
        delete records[req.headers.ssn]
        res.status(200).send({"msg": "Successfully deleted."});
        return;
    }
    else {
        res.status(401).send({"msg":"First or Last didn't match SSN. (Trying to delete)"})
        return;
    }
});


Final index.js

const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.json());

let patients = new Object();
patients["999991234"] = ["Jensen", "Watkins", "425-555-1234"]
patients["999995678"] = ["Patrick", "Bartholomew", "425-555-5678"]

let records = new Object();
records["999991234"] = "Status: Healthy"
records["999995678"] = "Status: Slight Cold"

// Get patient medical records
app.get("/records", (req, res) => {
    
    // Verify Patient Exists
    if (records[req.headers.ssn] === undefined) {
        res.status(404).send({"msg":"Patient not found."})
        return;
    }
    
    // Verify SSN matches First and last Name
    if (req.head
        ers.firstname == patients[req.headers.ssn][0] && req.headers.lastname == patients[req.headers.ssn][1]) {
        if (req.body.reasonforvisit === "medicalrecords") {
            // return medical records
            res.status(200).send(records[req.headers.ssn]);
            return;
        }
        else {
            // return error
            res.status(501).send({"msg":"Unable to complete request at this time: " + req.body.reasonforvisit})
            return;
        }
    }
    else {
        res.status(401).send({"msg":"First or Last didn't match SSN."})
        return;
    }

    // Return Appropriate Record
    res.status(200).send({"msg": "HTTP GET - SUCCESS!"});
});

// Create a new patient
app.post("/", (req, res) => {
    
    // Create patient in database
    patients[req.headers.ssn] = [req.headers.firstname, req.headers.lastname, req.headers.phone]
    res.status(200).send(patients)
});                                                                                                                                                                                                         

// Update existing patient phone number
app.put("/", (req, res) => {
    
    // Verify Patient Exists
    if (records[req.headers.ssn] === undefined) {
        res.status(404).send({"msg":"Patient not found."})
        return;
    }

    if (req.headers.firstname == patients[req.headers.ssn][0] && req.headers.lastname == patients[req.headers.ssn][1]) {
        // Update the phone number and return the patient info
        patients[req.headers.ssn] = [req.headers.firstname, req.headers.lastname, req.body.phone];
        res.status(202).send(patients[req.headers.ssn]);
        return;
    }
    else {
        res.status(401).send({"msg":"First or Last didn't match SSN. (Trying to update Ph #)"})
        return;
    }

});

// Delete patient records
app.delete("/", (req, res) => {

    // Verify Patient Exists
    if (records[req.headers.ssn] === undefined) {
        res.status(404).send({"msg":"Patient not found."})
        return;
    }
    
    // Verify SSN matches First and last Name
    if (req.headers.firstname == patients[req.headers.ssn][0] && req.headers.lastname == patients[req.headers.ssn][1]) {
        // Delete patient and medical records from database

        delete patients[req.headers.ssn]
        delete records[req.headers.ssn]
        
        res.status(200).send({"msg": "Successfully deleted."});
        return;
    }
    else {
        res.status(401).send({"msg":"First or Last didn't match SSN. (Trying to delete)"})
        return;
    }

});

app.listen(3000);


View it in Postman

  • In Terminal type: nodemon index.js


  • HTTP GE


  • HTTP PUT


  • HTTP POST


  • HTTP DELETE


Closing Thoughts

This project showcases a basic medical record system using an Express-based API, offering CRUD functionalities on patient data. The API manages patient data by allowing for retrieval, updates, additions, and deletions.

In the realm of Application Security (AppSec), understanding and securing REST APIs is crucial. These APIs are pivotal in modern web applications, facilitating smooth interactions between software components. Given their widespread use and the sensitive data they often handle, they're prime targets for cyber threats. As such, proficiency in both comprehending and safeguarding these APIs is essential for AppSec professionals, underlining the importance of this project as a foundational step.