🔒 CAPIE - Chapter 6

How to Secure Your REST API from Attackers

📖 Introduction

API stands for Application Programming Interface, which means we have an exposed interface that can be addressed programmatically. As the internet becomes available in more and more locations around the world, these types of interfaces will become ever more prevalent. Securing an API can easily cost as much as the feature development itself, which is why this guide aims to help you navigate this complex landscape.

💡 Key Point: While REST APIs are not the only kind of API, they serve a specific purpose, and understanding their security risks is crucial when implementing them.

🌐 What is a REST API?

REST stands for Representational State Transfer, which defines a programming architecture that uses HTTP Methods (GET, POST, DELETE, PATCH, etc.). Using these HTTP methods allows us to create APIs independent of the host operating system.

Properties of a RESTful API:

1. Client-Server Architecture

Clients use HTTP calls to communicate with the APIs.

2. Stateless

APIs do not account for already known information about the object being processed. States are never passed between requests.

3. Cacheable

Allows for caching of frequently used resources to improve performance.

4. Uniform Interface

Has a uniform way of communicating with other APIs.

5. URI-Based Variables

Variables are identified with the URI (e.g., /invoices/1/print).

6. Content-Type Headers

Contains headers describing the metadata of the API.

REST API Request Flow

Client Application
HTTP Request
REST API
Response

🛡️ Eight Security Principles of Secure REST APIs

Securing REST API endpoints requires careful planning. Here are eight fundamental security principles:

1. Least Privilege

A system should be analyzed carefully and should only be granted rights if absolutely needed. Permissions should be removed when no longer necessary.

Example: A user who only needs to read data should not have write or delete permissions.

2. Fail-Safe Defaults

Users should not have access to any resources by default. They should only be allowed to view resources after receiving explicit permissions.

Example: New API endpoints are locked down by default, requiring explicit permission grants.

3. Economy of Mechanism

The more complex a system and its interfaces are, the more chances there are for something to go wrong. Keep complexity as low as possible.

Example: Use simple, straightforward authentication mechanisms rather than complex custom solutions.

4. Complete Mediation

On every action executed by the system, verify whether the user is allowed to perform that action using a current list of user rights, not cached data.

Example: Check permissions on every API call, even if the user was authorized moments ago.

5. Open Design

Security should not depend on secrecy of design. Consider exposing internal software to bug bounties for better security.

Example: Use well-tested, open-source security libraries rather than proprietary "security through obscurity" approaches.

6. Separation of Privilege

Users should never gain access to a specified object based on one criterion. Multiple selection criteria should be used for fine-grained control.

Example: Require both role-based permissions AND resource ownership to modify data.

7. Least Common Mechanism

Think carefully about sharing states between calls. If you can corrupt the state at any point, the predefined flow might no longer work as expected.

Example: Avoid shared global state; use request-scoped contexts instead.

8. Psychological Acceptability

Security mechanisms should not add noticeable time to loading or user processes, or users will find workarounds.

Example: Don't force password changes every 30 days, as users may just increment a number.

🔐 Practical Principles for Securing REST APIs

1. Keep it Simple

The more functionality and complexity added to a system, the easier it is to overlook security aspects. Only maintain necessary complexity.

2. Use HTTPS

⚠️ Critical: HTTPS prevents Man-In-The-Middle (MITM) attacks that aim to intercept traffic between the browser and API.

HTTP vs HTTPS

❌ HTTP
Unencrypted
Vulnerable to MITM
✅ HTTPS
Encrypted (TLS/SSL)
Protected from MITM

Benefits: Prevents eavesdropping, builds customer trust, and improves conversion rates.

3. Password Hash

Passwords should always be hashed. In case of a database leak, passwords remain unreadable.

// Registration: Hash password before storing
hashedPassword = hash(userPassword + salt)
store(username, hashedPassword)
// Login: Hash input and compare
inputHash = hash(inputPassword + salt)
if (inputHash === storedHash) { loginUser() }
Recommended Algorithms:
  • bcrypt - Adaptive hash function with built-in salt
  • Argon2 - Winner of Password Hashing Competition
  • scrypt - Memory-hard function resistant to hardware attacks

4. Never Expose Information on URLs

⚠️ Security Risk: Sensitive information like API keys, usernames, and passwords should never appear in URLs.

❌ BAD: https://api.example.com/users?apikey=12345&password=secret
✅ GOOD: POST https://api.example.com/users with Authorization header

Why? URLs are logged in access logs, browser history, and referrer headers, compromising security.

5. API Access Control

API endpoints must always verify if the user is authorized to perform the requested action.

// Check permissions before executing action
if (!user.hasPermission('DELETE', resource)) { return 403 Forbidden }
if (!user.ownsResource(resource)) { return 403 Forbidden }
deleteResource(resource)

Access Control Flow

Request
Authenticate User
Check Permissions
Execute or Deny

6. Response Security Headers

Security headers instruct browsers to act in specific ways to protect against attacks.

Header Purpose
Cache-Control: no-store Prevent sensitive information from being cached
Content-Security-Policy: frame-ancestors 'none' Protect against drag-and-drop clickjacking attacks
Content-Type: application/json Specify the content type of the response
Strict-Transport-Security Require HTTPS connections and protect against spoofed certificates
X-Content-Type-Options: nosniff Prevent MIME sniffing and inappropriate interpretation as HTML
X-Frame-Options: DENY Protect against drag-and-drop clickjacking attacks
// Example response headers configuration
Cache-Control: no-store, no-cache, must-revalidate
Content-Security-Policy: frame-ancestors 'none'
Content-Type: application/json; charset=utf-8
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

7. Adding Timestamp in Request

Timestamps help prevent replay attacks by ensuring requests are only valid for a limited time window.

// Client sends request with timestamp
X-Timestamp: 2026-04-14T10:30:00Z
// Server validates timestamp
currentTime = getCurrentTime()
requestTime = parseTimestamp(request.headers['X-Timestamp'])
if (abs(currentTime - requestTime) > 120 seconds) { return 401 Unauthorized }
How it works: The server only processes requests within 1-2 minutes of the current time. If an attacker tries to replay a login request to brute force it, this provides basic protection.

8. Input Parameter Validation

⚠️ Critical: Implement strong validation before data reaches back-end logic. User input is unpredictable and potentially malicious.

// Validate input type and format
if (typeof input !== 'string') { return 400 Bad Request }
if (!isValidEmail(email)) { return 400 Bad Request }
if (input.length > MAX_LENGTH) { return 400 Bad Request }
if (!regex.test(input)) { return 400 Bad Request }
// Sanitize input to prevent injection attacks
sanitizedInput = escapeHtml(input)
Common Validation Rules:
  • Check data types (string, number, boolean)
  • Validate length and size limits
  • Use whitelisting for allowed characters
  • Sanitize to prevent SQL injection and XSS
  • Validate format (email, phone, URL, etc.)

⚡ Why REST API Security is Important

APIs are often points of integration, and from experience, this is where the biggest security issues arise. Just because there's no UI doesn't mean it's impossible to directly communicate with your API.

Common API Attack Vectors

Injection Attacks
Broken Authentication
Data Exposure
Access Control Issues
Security Misconfiguration
CSRF Attacks

🎯 Key Takeaways:

  • Always assume your API will be attacked
  • Security should be built in from the start, not added later
  • Regular security audits and penetration testing are essential
  • Stay updated with OWASP API Security Top 10
  • Implement defense in depth - multiple layers of security

📋 Security Checklist

✅ Implementation Checklist:

  • ☐ All API endpoints use HTTPS/TLS
  • ☐ Passwords are properly hashed (bcrypt, Argon2, or scrypt)
  • ☐ No sensitive data in URLs or query parameters
  • ☐ Authentication and authorization on every endpoint
  • ☐ Security headers properly configured
  • ☐ Request timestamps validated (1-2 minute window)
  • ☐ Input validation and sanitization implemented
  • ☐ Rate limiting to prevent brute force attacks
  • ☐ Logging and monitoring for suspicious activity
  • ☐ Regular security audits and updates