HIGH bola idorloopbackbasic auth

Bola Idor in Loopback with Basic Auth

BOLA IDOR in Loopback with Basic Auth — how this specific combination creates or exposes the vulnerability

BOLA (Broken Level of Authorization) / IDOR occurs when an API exposes an object identifier (e.g., a resource ID or username) and allows a caller to access or modify an object they should not own or lack permission to view. In LoopBack, this commonly arises when an endpoint like /api/users/{id} relies only on authentication (e.g., Basic Auth) to identify who is making the request, but does not enforce authorization checks that verify the requesting user is allowed to operate on the targeted resource.

When Basic Auth is used, LoopBack typically authenticates the request by validating the Base64-encoded credentials and attaches a user object to the request. While this establishes identity, it does not automatically enforce ownership or role-based permissions. If route definitions or underlying models do not explicitly scope data access to the authenticated user, an attacker can enumerate or manipulate IDs (e.g., incrementing numeric user IDs or cycling through UUIDs) and access other users’ data. Common patterns that lead to BOLA/IDOR include:

  • Using a model’s default scope or repository method that returns records without filtering by the authenticated user’s ID.
  • Exposing relationships (e.g., /api/users/{id}/profile) where the profile ID is controllable by the attacker and not validated against the authenticated subject.
  • Relying only on role-based access without verifying resource ownership (e.g., an admin role can read any user record, but there is no check to prevent a low-privilege user from requesting another user’s record by guessing the ID).

For example, consider a LoopBack application that uses Basic Auth and exposes a user profile endpoint. An authenticated request with valid credentials but no ownership check might look like this:

// GET /api/users/123
GET /api/users/123 HTTP/1.1
Host: api.example.com
Authorization: Basic dXNlcjpwYXNz

If the server resolves user 123 without confirming that the authenticated user corresponds to ID 123 (or that the authenticated user has the right to view it), the request succeeds but exposes another user’s data — a classic BOLA/IDOR. The presence of Basic Auth confirms who you are, but not whether you are allowed to see that specific resource.

LoopBack’s dynamic model definitions and remote methods can inadvertently allow this if ACLs are permissive or if developers forget to bind the request context to data access queries. Attackers may probe predictable IDs or abuse weakly scoped model relations to enumerate accounts, escalate access, or harvest sensitive profile information.

Basic Auth-Specific Remediation in Loopback — concrete code fixes

Remediation focuses on ensuring that every data access operation is scoped to the authenticated subject and that authorization checks are explicit and granular. With Basic Auth, LoopBack provides the authenticated user in req.accessToken.userId (or a similar context property depending on your User model configuration). Use this value to filter queries and enforce ownership at the repository or service layer.

Below are concrete examples of secure implementations in LoopBack.

1) Repository / Data-source query scoping

Ensure model queries always include a filter for the authenticated user. Avoid relying on default model scopes that return all records.

// In a repository or service method
async findProfilesByCurrentUser(userId) {
  const profiles = await this.profileRepository.find({
    where: {
      userId: userId, // explicitly scope to the authenticated user
    },
  });
  return profiles;
}

2) Remote method with explicit ownership check

In a LoopBack controller or service, validate that the requested ID matches the authenticated user’s ID before proceeding.

// common/controllers/user.controller.js
module.exports = function(User) {
  User.getProfile = async function(userId) {
    const UserModel = this; // reference to the User model
    const currentUserId = UserModel.app.get('auth').getCurrentUserId(); // obtain from request context
    if (!currentUserId || currentUserId !== userId) {
      const err = new Error('Unauthorized');
      err.statusCode = 403;
      throw err;
    }
    return UserModel.findById(userId, { include: 'profile' });
  };

  User.remoteMethod(
    'getProfile', {
      accepts: { arg: 'userId', type: 'string', required: true },
      returns: { arg: 'profile', type: 'object' },
      http: { path: '/profile', verb: 'get' },
    }
  );
};

3) Use LoopBack ACLs and role scopes cautiously

ACLs can restrict access at the model level, but they should complement resource-level checks, not replace them. For example, an ACL might allow authenticated users to read the User model, but you still need to ensure a given user can only read their own record via query filters.


// server/root.json (ACL example — model-level, not sufficient alone for BOLA)
[
  {
    "principalType": "ROLE",
    "principalId": "$everyone",
    "permission": "DENY",
    "property": "**"
  },
  {
    "principalType": "ROLE",
    "principalId": "$authenticated",
    "permission": "ALLOW",
    "property": "create",
    "accessType": "EXECUTE"
  },
  {
    "principalType": "ROLE",
    "principalId": "$owner",
    "permission": "ALLOW",
    "property": ["find", "findById", "updateAttributes"],
    "accessType": "READ",
    "permission": "ALLOW"
  }
]

Note: The above ACL is illustrative. The crucial part is binding $owner to the authenticated user’s ID at query time, which must be enforced in your repository or service logic as shown earlier.

4) Secure Basic Auth setup in LoopBack

Configure LoopBack’s built-in authentication component to use Basic Auth with proper user model scoping. Always transmit credentials over HTTPS to prevent interception.


// server/component-config.json
{
  "authentication": {
    "strategies": ["basic"],
    "accessToken": { "model": "accessToken" },
    "currentUserLiteral": "CURRENT_USER"
  },
  "basic": {
    "model": "user",
    "realm": "Secure API"
  }
}

Ensure your User model enforces uniqueness and proper validation to prevent ID guessing attacks. Combine this scoping approach with rate limiting and audit logging to detect enumeration attempts.

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

Why does Basic Auth alone not prevent BOLA/IDOR in LoopBack?
Basic Auth confirms identity but does not enforce data ownership. Without explicit scoping of queries to the authenticated user’s ID, an attacker can manipulate resource identifiers to access other users’ data.
What additional controls should be applied alongside Basic Auth to mitigate BOLA/IDOR?
Always filter data access by the authenticated user ID in repositories and remote methods, enforce granular ACLs that reference the request context, and implement rate limiting and logging to detect enumeration behavior.