Although it can be difficult to secure an API without standard user authentication, there are a number of easy steps you can take to guard against exploitation and unwanted access.
1. IP Whitelisting (IP Restriction)
Only allow requests from specified IP addresses.
- Using NGINX (as a reverse proxy):
http {
...
server {
...
location /api {
# Restrict API access to these IPs
allow 192.168.1.100;
allow 2001:0db8:85a3:0000:0000:8a2e:0370:7334;
deny all; # Deny all other IP addresses
}
}
}
- Using AWS API Gateway: Configure "Resource Policy" to restrict source IP addresses.
2. Rate Limiting
Limit the number of requests from an IP address within a time frame.
- Using Node.js with Express and rate-limit middleware:
const rateLimit = require("express-rate-limit");
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests per `window` (here, per 15 minutes)
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
legacyHeaders: false, // Disable the `X-RateLimit-*` headers
});
// Apply to all API endpoints
app.use("/api/", limiter);
- Using Cloudflare: Enable the "Rate Limiting" rule in the dashboard.
3. API Tokens (without User Auth)
Require a static, secret token to be passed with each request.
from flask import Flask, request, abort
app = Flask(__name__)
API_TOKEN = "your_secret_static_token_here"
@app.before_request
def require_api_token():
if request.headers.get('X-API-TOKEN') != API_TOKEN:
abort(401)
@app.route('/api/endpoint')
def protected_endpoint():
return "Access granted."
4. User Agent Restriction
Restrict access based on the User-Agent header.
SetEnvIf User-Agent "^YourApprovedBotName" let_in
Order Deny,Allow
Deny from all
Allow from env=let_in
5. Content Security Policy (CSP) and CORS
Define which sources of content are allowed to interact with your API.
- Implementing CORS with Python and Flask to only allow specific origins:
from flask import Flask
from flask_cors import CORS, cross_origin
app = Flask(__name__)
cors = CORS(app, resources={r"/api/*": {"origins": "https://example.com"}})
- CSP with NGINX for API responses:
http {
...
server {
...
location /api {
# Other configurations
add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://example.com;";
}
}
}