HIGH bola idorkoabearer tokens

Bola Idor in Koa with Bearer Tokens

Bola Idor in Koa with Bearer Tokens — how this specific combination creates or exposes the vulnerability

Broken Object Level Authorization (BOLA) occurs when an API exposes endpoints that identify resources with user-supplied identifiers and fail to enforce that the authenticated subject is authorized to access that specific object. In a Koa application using Bearer Tokens for authentication, the vulnerability arises when token validation is performed but the request logic does not confirm the resource owner matches the token’s subject. A common pattern is to verify the token, extract a user identifier (e.g., userId), and then directly use an incoming parameter such as :id to query a database without checking ownership or role-based permissions.

Consider a Koa endpoint designed to retrieve a user’s profile: GET /users/:id. If the handler only validates the Bearer Token and then executes SELECT * FROM users WHERE id = :id without comparing :id to the userId from the token, an attacker can modify the :id path or query parameter to access any user’s record. Because Bearer Tokens are often used in APIs and single-page apps, developers may assume transport-layer security (HTTPS) and token validation are sufficient, inadvertently skipping object-level checks. Middleware that sets ctx.state.user from the token is helpful, but if later code uses route parameters directly, the authorization gap remains.

BOLA is frequently combined with other issues such as Insecure Direct Object References (IDOR) when the API exposes predictable numeric or UUID identifiers. For example, an endpoint like GET /accounts/:accountId may return data for account 12345 even if the Bearer Token belongs to a user who should only see account 10001. In a black-box scan, such endpoints are probed by iterating over known or guessed identifiers and observing whether unauthorized data is returned. Because Koa does not enforce authorization at the framework level, this responsibility falls entirely on the developer to implement checks after authentication.

Real-world attack patterns mirror scenarios described in OWASP API Top 10 (2023), specifically Broken Object Level Authorization. Adversaries may use authenticated sessions with Bearer Tokens to enumerate resources, leveraging predictable IDs or leveraging access patterns to infer relationships. In some cases, vertical privilege escalation can occur if role claims in the token are not validated alongside object ownership, allowing a lower-privilege user to access admin-oriented endpoints by manipulating :id or query parameters. The use of Bearer Tokens does not prevent BOLA; it simply changes the authentication surface. Detection often involves authenticated probing with modified identifiers while keeping the same token, confirming that the server enforces per-object authorization.

An example of vulnerable Koa code illustrates the problem clearly. The handler verifies the token and attaches user information to ctx.state, but then uses the route parameter directly in the data access logic. Because there is no check that the resource’s owner matches ctx.state.user.id, any valid token allows traversal across object boundaries. This pattern is common in tutorials and early-stage APIs, and it persists in production when authorization is treated as an afterthought.

Bearer Tokens-Specific Remediation in Koa — concrete code fixes

To remediate BOLA in Koa with Bearer Tokens, ensure that every data access operation validates that the resource belongs to the authenticated subject. This means after verifying the token and populating ctx.state.user, you must add explicit ownership checks before returning or modifying a resource. Avoid using raw route parameters directly in queries; instead, construct queries that filter by both the resource identifier and the user identifier derived from the token.

Below is a secure Koa handler example that demonstrates proper authorization. It uses a Bearer Token extracted from the Authorization header, verifies it (placeholder validateJwt), and ensures the requested user ID matches the token’s subject before proceeding. This pattern can be extended to other resources such as accounts, posts, or tenants by applying the same ownership principle.

import Koa from 'koa';
import Router from 'koa-router';

const app = new Koa();
const router = new Router();

// Placeholder: replace with actual JWT validation and user lookup
async function validateBearerToken(token: string): Promise<{ userId: string; scopes: string[] }> {
  // Verify signature, expiry, and extract subject (sub) or user identifier
  // Return an object with at least the user identifier
  return { userId: 'user-uuid-123', scopes: ['read:profile'] };
}

router.get('/users/:id', async (ctx) => {
  const auth = ctx.request.header.authorization;
  if (!auth || !auth.startsWith('Bearer ')) {
    ctx.status = 401;
    ctx.body = { error: 'Unauthorized' };
    return;
  }
  const token = auth.slice(7);
  const payload = await validateBearerToken(token);
  if (!payload) {
    ctx.status = 401;
    ctx.body = { error: 'Invalid token' };
    return;
  }

  // Enforce BOLA: ensure the requested ID matches the token subject
  const requestedId = ctx.params.id;
  if (requestedId !== payload.userId) {
    ctx.status = 403;
    ctx.body = { error: 'Forbidden: insufficient permissions on this resource' };
    return;
  }

  // Proceed to fetch the resource knowing the subject owns it
  const user = await getUserById(requestedId); // your data access layer
  if (!user) {
    ctx.status = 404;
    ctx.body = { error: 'Not found' };
    return;
  }
  ctx.body = user;
});

// Example for a nested resource, such as an account
router.get('/accounts/:accountId', async (ctx) => {
  const auth = ctx.request.header.authorization;
  if (!auth || !auth.startsWith('Bearer ')) {
    ctx.status = 401;
    ctx.body = { error: 'Unauthorized' };
    return;
  }
  const token = auth.slice(7);
  const payload = await validateBearerToken(token);
  if (!payload) {
    ctx.status = 401;
    ctx.body = { error: 'Invalid token' };
    return;
  }

  const accountId = ctx.params.accountId;
  // Ownership check: verify the account belongs to the user identified by the token
  const account = await getAccountByIdAndOwner(accountId, payload.userId);
  if (!account) {
    ctx.status = 404;
    ctx.body = { error: 'Not found or access denied' };
    return;
  }
  ctx.body = account;
});

app.use(router.routes()).use(router.allowedMethods());

Key points in the remediation:

  • Always compare the resource identifier (e.g., :id or :accountId) to the user identifier obtained from the Bearer Token payload.
  • Use parameterized queries in your data access layer that include both the resource ID and the owner ID to prevent SQL injection and ensure row-level security.
  • Return 403 Forbidden when the IDs do not match, rather than 404, to avoid leaking existence via timing differences, unless your threat model requires indistinguishability.
  • For endpoints that involve multiple ownership layers (e.g., /orgs/:orgId/projects/:projectId), validate that the subject has membership or explicit permission on the parent resource as well.

middleBrick can help identify BOLA patterns during scans by correlating OpenAPI/Swagger specs with runtime behavior, especially when endpoints expose predictable identifiers without explicit ownership checks. While it does not fix the code, its findings include remediation guidance to tighten authorization logic. If you use the CLI (middlebrick scan ) or the GitHub Action to add API security checks to your CI/CD pipeline, you can fail builds when risky endpoints are detected before they reach production.

Related CWEs: bolaAuthorization

CWE IDNameSeverity
CWE-250Execution with Unnecessary Privileges HIGH
CWE-639Insecure Direct Object Reference CRITICAL
CWE-732Incorrect Permission Assignment HIGH

Frequently Asked Questions

Does using JWTs in Bearer Tokens prevent BOLA in Koa?
No. JWTs provide authentication and a payload with claims, but they do not enforce object-level authorization. You must still compare the resource identifier (e.g., user ID) from the token with the requested resource ID in each handler to prevent BOLA.
Can middleBrick fix BOLA vulnerabilities automatically?
middleBrick detects and reports BOLA findings with remediation guidance, but it does not automatically fix code. Developers must implement ownership checks in Koa handlers and other API logic based on the provided guidance.