Skip to content
IRC-CodingIRC-Coding
REST API SecurityAuthenticationAuthorizationOAuth 2.0JWTRBACCORSAPI Security

REST API Security: Authentication & Authorization

Master REST API security: authentication vs authorization, OAuth 2.0, JWT, RBAC, CORS, CSRF, and best practices.

S

schutzgeist

12 min read
REST API Security: Authentication & Authorization

REST API Security: Authentication, Authorization, and Protective Measures

REST API security ensures that only authorized clients can access authorized resources. Anyone building APIs must understand authentication and authorization—they’re the foundation of every secure interface.

What is REST API Security?

REST API security encompasses all measures that protect a RESTful API from unauthorized access, manipulation, and attacks. It rests on two core pillars:

Authentication answers: Who are you? The client proves its identity through tokens, API keys, certificates, or session cookies.

Authorization answers: Are you allowed to do this? After authentication, the system checks whether the identified client has permission to perform the requested action.

This separation is essential. An authenticated user isn’t automatically authorized to do everything. A user can read their own data but not someone else’s. An admin can do more than an editor. This distinction is captured by models like RBAC (Role-Based Access Control) or ABAC (Attribute-Based Access Control).

Who uses REST API Security?

  • Backend developers implement auth middleware and authorization logic
  • API designers define which endpoints need which protection
  • DevOps engineers configure TLS, rate limiting, and API gateways
  • Security engineers audit APIs for vulnerabilities
  • Frontend developers must send auth tokens correctly with requests

Why This Matters in Computer Science and Exams

The OWASP Top 10 lists Broken Access Control at number 1 and Cryptographic Failures at number 2—both directly affect API security. In professional certifications, computer science courses, and exams, questions regularly cover the differences between authentication and authorization, OAuth 2.0, JWT, and security headers.

Core Concepts in Detail

Authentication Methods for REST APIs

API Key

The client sends a static key in the X-API-Key header. The server compares it against its database.

Advantages: simple, works well for server-to-server communication. Disadvantages: no expiration, no granular permissions, full access if compromised.

Session-Based Authentication

The client sends credentials (username and password). The server creates a session, stores it on the server, and returns a session ID in a cookie. On each subsequent request, the cookie is sent automatically.

Advantages: server-side control, sessions can be invalidated at any time. Disadvantages: poor scaling across multiple instances (requires a shared session store), CSRF risk with cookies.

Token-Based Authentication (JWT)

The client sends credentials. The server creates a JSON Web Token (JWT) containing claims like user ID, roles, and expiration time. The token is cryptographically signed. The client sends it with each request in the Authorization: Bearer <token> header.

Advantages: stateless, scales well, no session store needed. Disadvantages: tokens can’t easily be revoked before expiration (except with revocation lists or blacklists).

OAuth 2.0

OAuth 2.0 is a framework for delegated authorization. A client obtains an access token from an authorization server after the resource owner (the user) grants consent. The token permits access to specific resources for a limited time.

Common flows:

  • Authorization Code Flow: standard for web apps with a server backend
  • PKCE Flow: for single-page applications and mobile apps without a client secret
  • Client Credentials Flow: for server-to-server communication without user involvement

Authorization Models

RBAC (Role-Based Access Control)

Users are assigned roles. Roles have permissions. The check is: Does the user have a role that permits this action?

Example: the admin role can do anything, the editor role can read and write, the viewer role can only read.

Advantages: easy to understand, works well for manageable systems. Disadvantages: role explosion when permissions are very granular.

ABAC (Attribute-Based Access Control)

Access control is based on attributes of the subject, resource, action, and environment. The check is: Do all attribute combinations satisfy the policy?

Example: A doctor can read patient data only during working hours and only for patients in their department.

Advantages: very granular, policy-driven. Disadvantages: more complex to implement and maintain.

Resource Owner or Ownership-Based Authorization

A user can access only resources they own. An order can be viewed only by its owner. The check requires a database query: Does this resource belong to the authenticated user?

Additional Security Measures

TLS (Transport Layer Security)

Every API must run over HTTPS. Without TLS, tokens and credentials can be intercepted. TLS encrypts the transport channel and guarantees the integrity of transmitted data.

CORS (Cross-Origin Resource Sharing)

CORS controls which external origins may access the API. The server sends Access-Control-Allow-Origin headers. Without correct CORS configuration, browser-based clients may be blocked—or worse, arbitrary origins may gain access.

CSRF Protection

Cookie-based authentication carries CSRF risk. An attacker can trick a browser into automatically sending a cookie. Protective measures include CSRF tokens, the SameSite cookie attribute, and using the Authorization header instead of cookies.

Rate Limiting

Limits the number of requests per client within a time window. Protects against brute-force attacks, credential stuffing, and DoS. Typical: 100 requests per minute per token.

Input Validation

Every input must be validated. SQL injection, XSS, and command injection arise from missing or insufficient validation. Use prepared statements, schema validation, and whitelisting.

Why REST API Security Matters in Practice

An insecure API is an open door to your data. Here are realistic scenarios:

  • Token leak: An access token is stored in logs or hardcoded in client code. An attacker finds it and gains access to all data belonging to that user.
  • Broken Object Level Authorization (BOLA): The API checks only whether the user is authenticated, not whether they can access the requested resource. A user calls /api/orders/42 and sees another user’s order.
  • Mass Assignment: The client sends a field like {"role":"admin"} during a profile update. The server accepts it unchecked. The user makes themselves an admin.
  • No Rate Limiting: An attacker tries 10,000 passwords per second. Without rate limiting, they crack the password in minutes.

Practical Example: Express.js API with JWT and RBAC

This example shows a complete REST API with authentication (JWT) and authorization (RBAC). It demonstrates the core concepts in compact code: token creation, middleware-based auth checks, role-based access control, and ownership verification.

// auth-middleware.js
// Middleware: Verifies JWT from the Authorization header
function authenticate(req, res, next) {
  const authHeader = req.headers.authorization;
  if (!authHeader || !authHeader.startsWith('Bearer ')) {
    return res.status(401).json({
      error: 'UNAUTHORIZED',
      message: 'Authentication required. Send a Bearer token.'
    });
  }

  const token = authHeader.split(' ')[1];
  try {
    // jwt.verify throws an exception if the token is invalid or expired
    const payload = jwt.verify(token, process.env.JWT_SECRET);
    req.user = payload; // { userId: 42, role: 'editor', exp: 1234567890 }
    next();
  } catch (err) {
    return res.status(401).json({
      error: 'INVALID_TOKEN',
      message: 'Token is invalid or expired.'
    });
  }
}

// Middleware: Checks whether the user has one of the required roles
function authorize(...roles) {
  return (req, res, next) => {
    if (!req.user) {
      return res.status(401).json({
        error: 'UNAUTHORIZED',
        message: 'Authentication required.'
      });
    }
    if (!roles.includes(req.user.role)) {
      return res.status(403).json({
        error: 'FORBIDDEN',
        message: `Required role: ${roles.join(' or ')}.`
      });
    }
    next();
  };
}

// Middleware: Checks whether the user owns the resource
function checkOwnership(getResourceId) {
  return async (req, res, next) => {
    const resourceId = getResourceId(req);
    const resource = await db.orders.findById(resourceId);
    if (!resource) {
      return res.status(404).json({
        error: 'NOT_FOUND',
        message: 'Resource not found.'
      });
    }
    // Admins can access anything, others only their own resources
    if (req.user.role !== 'admin' && resource.userId !== req.user.userId) {
      return res.status(403).json({
        error: 'FORBIDDEN',
        message: 'You can only access your own resources.'
      });
    }
    req.resource = resource;
    next();
  };
}
// routes.js
// Applying middleware to various endpoints

// Login: Authentication -> issue JWT
app.post('/api/login', async (req, res) => {
  const { email, password } = req.body;
  const user = await db.users.findByEmail(email);
  if (!user || !await bcrypt.compare(password, user.passwordHash)) {
    return res.status(401).json({
      error: 'INVALID_CREDENTIALS',
      message: 'Invalid email or password.'
    });
  }
  const token = jwt.sign(
    { userId: user.id, role: user.role },
    process.env.JWT_SECRET,
    { expiresIn: '15m' }
  );
  res.json({ token });
});

// Protected routes: authenticate for all, authorize for specific roles
app.get('/api/orders', authenticate, async (req, res) => {
  // Regular users see only their own orders
  if (req.user.role === 'admin') {
    const orders = await db.orders.findAll();
    res.json(orders);
  } else {
    const orders = await db.orders.findByUserId(req.user.userId);
    res.json(orders);
  }
});

app.get('/api/orders/:id', authenticate, checkOwnership(req => req.params.id), (req, res) => {
  res.json(req.resource);
});

app.post('/api/orders', authenticate, async (req, res) => {
  const order = await db.orders.create({
    ...req.body,
    userId: req.user.userId
  });
  res.status(201).json(order);
});

app.delete('/api/orders/:id', authenticate, authorize('admin'), checkOwnership(req => req.params.id), async (req, res) => {
  await db.orders.delete(req.params.id);
  res.status(204).send();
});

Detailed Information

Token Lifespan and Refresh Tokens

Access tokens should be short-lived (15 minutes). Refresh tokens last longer (days to weeks) and serve only to obtain new access tokens. If an access token is compromised, it remains useful only briefly. If a refresh token is compromised, it can be revoked server-side.

JWT Structure

A JWT consists of three Base64-encoded parts: header, payload, and signature. The header contains the algorithm and token type. The payload contains claims such as sub (subject), exp (expiration), iat (issued at), role, and userId. The signature is computed using a secret or private key.

Important: the payload is only Base64-encoded, not encrypted. Never store sensitive data in a JWT. Security comes from the signature—it guarantees the token hasn’t been tampered with.

Security Headers for REST APIs

HeaderPurpose
Strict-Transport-SecurityEnforces HTTPS
X-Content-Type-Options: nosniffPrevents MIME sniffing
X-Frame-Options: DENYPrevents clickjacking
Cache-Control: no-storePrevents caching of sensitive responses
Access-Control-Allow-OriginCORS configuration

Common Vulnerabilities (OWASP API Security Top 10)

  1. BOLA (Broken Object Level Authorization): No ownership check
  2. Broken Authentication: Weak token creation, no rate limits
  3. Excessive Data Exposure: API returns more fields than necessary
  4. Lack of Resources & Rate Limiting: No request throttling
  5. Broken Function Level Authorization: No role checks per endpoint
  6. Mass Assignment: Unfiltered acceptance of input fields
  7. Security Misconfiguration: Default secrets, debug mode, open CORS

Best Practices Summary

  • Always use HTTPS exclusively
  • Keep access tokens short-lived (15 min), make refresh tokens revocable
  • Use RBAC for coarse permissions, ABAC for granular policies
  • Perform ownership checks on every endpoint that accesses specific resources
  • Apply rate limiting at both IP and token level
  • Validate input with schemas and whitelisting
  • Never include sensitive data in JWT payloads
  • Set security headers
  • Return error messages without internal details
  • Conduct regular security audits and penetration tests

FAQ: REST API Security

1. What is the difference between authentication and authorization?

Authentication verifies the identity of a client (who are you?), while authorization checks whether the authenticated client has permission to perform a specific action (are you allowed to do this?). Authentication typically happens via login with credentials, while authorization occurs through role or attribute checks.

2. What is RBAC?

RBAC (Role-Based Access Control) is an authorization model where users are assigned roles and roles have permissions. Access control checks whether the user holds the required role. It’s straightforward to understand but can suffer from role explosion when dealing with fine-grained permissions.

3. What is ABAC?

ABAC (Attribute-Based Access Control) is an authorization model where access control is based on attributes of the subject, resource, action, and environment. Policies define which attribute combinations permit access. ABAC is more granular than RBAC but more complex to implement.

4. What is Broken Object Level Authorization (BOLA)?

BOLA is the most common API vulnerability according to OWASP. The API checks whether the user is authenticated but not whether they have permission to access the requested resource. A user can access someone else’s data by changing the ID in the URL. Protection: perform an ownership check at every endpoint.

5. Why should access tokens be short-lived?

Access tokens should be short-lived (for example, 15 minutes) because if compromised, they remain useful only briefly. Longer lifespans mean higher risk. For longer sessions, refresh tokens are used—they can be revoked server-side.

6. What is the difference between JWT and session cookies?

JWT is stateless—the server stores no session state; all information is contained in the token. Session cookies require a server-side session store. JWT scales better but is harder to revoke. Sessions are simpler to invalidate but require shared state across multiple servers.

7. What is mass assignment and how do you prevent it?

Mass assignment occurs when the server uncritically accepts all input fields. A client could send a field like role: admin and grant itself admin rights. Protection: use explicit field selection (whitelisting), DTOs containing only allowed fields, and validate all input.

8. Why is CORS important for API security?

CORS (Cross-Origin Resource Sharing) controls which external origins can access your API from the browser. Without CORS configuration, you may block legitimate browser clients or—if too permissive—allow any website to access your API. The correct approach is to allowlist specific origins.

9. What is CSRF and how does it affect REST APIs?

CSRF (Cross-Site Request Forgery) occurs when an attacker tricks a user’s browser into making a request to your API, with the session cookie automatically attached. With token-based authentication in the Authorization header, CSRF isn’t a risk since the browser doesn’t automatically send custom headers. With cookie-based auth, use CSRF tokens and SameSite attributes.

10. Are JWT payloads encrypted?

No, the JWT payload is only Base64-encoded, not encrypted. Anyone who intercepts the token can read the payload. Security comes from the signature, which prevents tampering. For confidential content, use JWE (JSON Web Encryption).

11. What is the PKCE flow in OAuth 2.0?

PKCE (Proof Key for Code Exchange) extends the Authorization Code Flow for SPAs and mobile apps that cannot securely store a client secret. The client generates a code verifier and sends its hash (code challenge) to the authorization server. During token exchange, the client must send the original verifier, making interception of the authorization code useless.

12. How does rate limiting work for APIs?

Rate limiting restricts the number of requests a client can make within a time window. Common approaches include fixed window (e.g., 100 requests per minute), sliding window, and token bucket. Limits can be based on IP address, API key, or token. When exceeded, the server responds with 429 Too Many Requests and includes a Retry-After header.

13. Which HTTP status codes are relevant for authentication errors?

401 Unauthorized means authentication is missing or invalid. 403 Forbidden means the client is authenticated but lacks permission for the requested action. 429 Too Many Requests indicates too many requests have been sent.

14. What is the principle of least privilege?

The principle of least privilege states that every client and user should have only the minimum permissions necessary for their task. A read-only client shouldn’t have write access. An editor shouldn’t have admin rights. This minimizes the attack surface if a credential is compromised.

15. How do you revoke a JWT before it expires?

Since JWT is stateless, it cannot be revoked outright. Solutions include maintaining a revocation list (blacklist) server-side and checking it with every request, or using short token lifespans with revocable refresh tokens. On logout, the associated refresh token can be invalidated, preventing new access tokens from being issued.

Next in the API Learning Path

The next article in the API learning path covers API Security Best Practices: protecting, securing, and operating APIs — the essential security measures for API operations following OWASP guidelines and industry best practices.

Sources and Further Resources

  1. https://owasp.org/API-Security/editions/2023/en/0x11-t10/
  2. https://datatracker.ietf.org/doc/html/rfc6749 (OAuth 2.0)
  3. https://datatracker.ietf.org/doc/html/rfc7519 (JWT)
  4. https://owasp.org/www-project-top-ten/
  5. https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html

Book Recommendations for API Development

API Development

Books about API design, REST, GraphQL, OpenAPI and API architecture

Designing Data-Intensive Applications von Martin Kleppmann

Designing Data-Intensive Applications von Martin Kleppmann

Bei Amazon ansehen

Affiliate-Link: Bei einem Kauf erhalten wir möglicherweise eine Provision.

API Design Patterns von JJ Geewax

API Design Patterns von JJ Geewax

Bei Amazon ansehen

Affiliate-Link: Bei einem Kauf erhalten wir möglicherweise eine Provision.

Back to Blog
Share:

Related Posts