Skip to content
RESTful API Security Guide: Authentication, Authorization & Best Practices

RESTful API Security Guide: Authentication, Authorization & Best Practices

DodaTech Updated Jun 6, 2026 7 min read

REST API security protects endpoints through authentication, authorization, encryption, and rate limiting — preventing unauthorized access at every layer.

What You’ll Learn

  • Authentication methods: API keys, JWT, OAuth 2.0
  • Authorization patterns: RBAC and scope-based access
  • HTTPS, TLS, and transport layer security
  • Rate limiting, input validation, and CORS
  • Security headers and audit logging

Why REST Security Matters

Exposing an API without security is like leaving your front door unlocked with a sign saying “come in.” Every public API is constantly scanned by bots looking for vulnerabilities. DodaTech’s Durga Antivirus Pro API handles sensitive threat data and user information — a breach would expose millions of users’ security status. That’s why every endpoint requires authentication, requests are rate-limited, and all traffic is encrypted with TLS 1.3.

    flowchart LR
    subgraph "Security Layers"
        A["HTTPS/TLS\nEncryption"]
        B["Authentication\nWho are you?"]
        C["Authorization\nWhat can you do?"]
        D["Rate Limiting\nHow many?"]
        E["Input Validation\nIs data clean?"]
    end
    A --> B --> C --> D --> E
    style A fill:#dbeafe,stroke:#2563eb
    style B fill:#fef3c7,stroke:#d97706
    style C fill:#fef3c7,stroke:#d97706
    style D fill:#fef3c7,stroke:#d97706
    style E fill:#dcfce7,stroke:#16a34a
  
Prerequisites: Understanding of REST, RESTful Messages, and HTTP.

Authentication vs Authorization

These two terms are often confused. Let’s clarify:

  • Authentication = “Who are you?” — verifying identity (login, API key, JWT)
  • Authorization = “What can you do?” — checking permissions (admin, read-only, etc.)

Think of a nightclub: authentication is showing your ID at the door. Authorization is the VIP wristband that lets you access the VIP lounge.

HTTPS and TLS

Everything starts with HTTPS. Without encryption, credentials and data travel in plain text.

// ❌ Insecure — credentials visible to anyone on the network
GET http://api.durga-antivirus.com/v1/threats
Authorization: Bearer my-super-secret-token

// ✅ Secure — everything is encrypted
GET https://api.durga-antivirus.com/v1/threats
Authorization: Bearer my-super-secret-token

Why HTTPS first: HTTPS encrypts the entire request — headers, body, and query parameters. An attacker on the same Wi-Fi network cannot read your JWT token, API key, or response data. Always enforce HTTPS at the infrastructure level (load balancer, API gateway) before any code runs.

API Keys

The simplest authentication method — a unique key identifies the client:

GET /api/v1/threats?api_key=abc123def456 HTTP/1.1

// Better: use a header
GET /api/v1/threats HTTP/1.1
X-API-Key: abc123def456

Pros: Simple, fast, easy to generate and revoke. Cons: No identity granularity — everyone with the same key has the same permissions. Vulnerable to leaking (keys in URLs, logs, source code).

JWT (JSON Web Tokens)

JWT is the most common authentication method for REST APIs. A JWT contains encoded JSON data signed by the server.

POST /auth/login HTTP/1.1
Content-Type: application/json

{"username": "admin", "password": "securepass123"}

---
HTTP/1.1 200 OK
{"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkFkbWluIiwicm9sZSI6ImFkbWluIn0.sflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"}

The client includes this token in every subsequent request:

GET /api/v1/threats HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Why JWT is stateless: The server doesn’t store the token. It verifies the signature, decodes the payload (user ID, role, expiration), and processes the request. This aligns perfectly with REST’s stateless constraint.

// Verifying a JWT — no session lookup needed
const jwt = require('jsonwebtoken');

function authenticate(req, res, next) {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) return res.status(401).json({ error: 'No token' });

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded; // { sub, name, role, iat, exp }
    next();
  } catch (err) {
    return res.status(401).json({ error: 'Invalid token' });
  }
}

Authorization with RBAC

Role-Based Access Control assigns permissions based on roles:

function authorize(...allowedRoles) {
  return (req, res, next) => {
    if (!allowedRoles.includes(req.user.role)) {
      return res.status(403).json({ error: 'Insufficient permissions' });
    }
    next();
  };
}

// Usage
app.get('/api/v1/admin/users', authenticate, authorize('admin'), handler);
app.get('/api/v1/threats', authenticate, authorize('admin', 'analyst', 'readonly'), handler);

Rate Limiting

Rate limiting prevents abuse by restricting how many requests a client can make in a time window:

// Simple in-memory rate limiter
const rateLimit = new Map();

function rateLimitMiddleware(req, res, next) {
  const key = req.ip || req.headers['x-forwarded-for'];
  const now = Date.now();
  const windowMs = 60000; // 1 minute
  const maxRequests = 100;

  if (!rateLimit.has(key)) {
    rateLimit.set(key, []);
  }

  const timestamps = rateLimit.get(key).filter(t => now - t < windowMs);
  timestamps.push(now);
  rateLimit.set(key, timestamps);

  if (timestamps.length > maxRequests) {
    return res.status(429).json({
      error: { code: 'RATE_LIMIT', message: 'Too many requests' }
    });
  }

  next();
}

Common Mistakes

1. Sending API Keys in URLs

GET /api/data?api_key=secret — keys in URLs appear in server logs, browser history, and referrer headers. Always use the Authorization header or X-API-Key header.

2. Not Validating Input

eval() on user input, $where in MongoDB, raw SQL interpolation — these lead to injection attacks. Always validate and sanitize all input. Use parameterized queries for databases.

3. Exposing Too Much in Error Messages

❌ "Database error: Connection failed to mysql://root:password@localhost:3306"
✅ "Internal server error. Request ID: req-abc-123"

Error messages should be helpful to developers but never expose internal system details.

4. Ignoring CORS

Without CORS headers, browsers block frontend apps from calling your API:

Access-Control-Allow-Origin: https://dashboard.durga-antivirus.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Authorization, Content-Type

5. Not Protecting Against Brute Force

Without rate limiting on authentication endpoints, attackers can try millions of passwords. Add rate limiting specifically on /auth/login with lower thresholds (5 attempts per minute).

6. Disabling HTTPS in Development and Forgetting in Production

APIs deployed without HTTPS expose user data in transit. Use Let’s Encrypt for free TLS certificates and enforce HTTPS with HSTS headers.

Practice Questions

  1. What is the difference between authentication and authorization?
  2. Why is JWT preferred over server-side sessions for REST APIs?
  3. What security problem does HTTPS solve?
  4. Why should API keys never be sent in URLs?
  5. What is the purpose of the 403 Forbidden status code?

Answers:

  1. Authentication verifies identity (“who are you?”). Authorization determines permissions (“what can you do?”).
  2. JWT is stateless — the token contains all user information, verified by signature. No server-side storage needed, enabling horizontal scaling.
  3. HTTPS encrypts all data in transit using TLS, preventing eavesdropping, tampering, and man-in-the-middle attacks on the network.
  4. API keys in URLs appear in server logs, browser history, referrer headers, and can be leaked through caching layers.
  5. 403 Forbidden indicates the client is authenticated but lacks permission to access the resource.

Challenge: Design an authentication and authorization system for Durga Antivirus Pro’s API with three user roles: admin (full access), analyst (view threats, submit samples), and customer (view own devices only). Show the JWT payload structure and middleware pseudocode.

FAQ

What is the difference between JWT and OAuth 2.0?
: JWT is a token format. OAuth 2.0 is an authorization framework that defines how tokens are obtained and used. They work together — OAuth 2.0 often issues JWT tokens. Use JWT for first-party APIs (your app uses your API). Use OAuth 2.0 when third-party apps need delegated access.
Should I validate JWTs on every request?
: Yes. Validate the signature, expiration (exp), and issuer (iss) on every request. JWT verification is fast (just cryptographic signature check) and maintains statelessness. Never trust a JWT without verification — anyone can craft a fake token.
How do I revoke a JWT before it expires?
: JWTs are stateless — they can’t be revoked server-side without a blacklist (which breaks statelessness). Best practices: use short expiration times (5–15 minutes for access tokens) plus a refresh token mechanism. For immediate revocation, maintain a blocklist of token IDs (jti claim) in Redis.
What is CORS and why does my API need it?
: CORS (Cross-Origin Resource Sharing) controls which web domains can access your API from browser JavaScript. Without CORS headers, browsers enforce the same-origin policy and block cross-domain requests. Only needed if a browser-based frontend calls your API from a different origin.

Try It Yourself

Generate and verify a JWT using Node.js:

const jwt = require('jsonwebtoken');

// Generate a token
const payload = { sub: 'user-123', name: 'SecurityAnalyst', role: 'analyst' };
const secret = 'your-256-bit-secret';
const token = jwt.sign(payload, secret, { expiresIn: '1h' });
console.log('Token:', token);

// Verify the token
try {
  const decoded = jwt.verify(token, secret);
  console.log('Verified:', decoded);
} catch (err) {
  console.error('Invalid token');
}

Run this and notice how the token contains all user information. No database lookup needed to verify — that’s stateless authentication.

What’s Next

TopicDescription
RESTful APIs OverviewReview all REST constraints together
Firebase vs Custom AuthCompare DIY auth with Firebase Authentication
GraphQL SecuritySecurity considerations in GraphQL APIs
HTTP Security HeadersSecurity headers like CSP, HSTS, X-Frame-Options

What’s Next

Congratulations on completing this Restful Security tutorial! Here’s where to go from here:

  • Practice daily — Consistency is more important than long study sessions
  • Build a project — Apply what you learned by building something real
  • Explore related topics — Check out other tutorials in the same category
  • Join the community — Discuss with other learners and share your progress

Remember: every expert was once a beginner. Keep coding!

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro