Search code examples
loopbackjsstrongloop

StrongLoop: POST access not being blocked


I'm using ACL rules to block all types of accesses from all the users. It is working for GET access but it is NOT working for POST accesses.

Any idea what could be wrong?

Here is the code and sample results:

/common/models/client.json

{
  "name": "client",
  "plural": "clients",
  "base": "User",
  "idInjection": true,
  "properties": {},
  "validations": [],
  "relations": {},
  "acls": [
    {
      "accessType": "*",
      "principalType": "ROLE",
      "principalId": "$everyone",
      "permission": "DENY"
    }
  ],
  "methods": {}
}

GET access error (working as expected, it is blocked):

CURL

curl -X GET --header "Accept: application/json" "http://localserver:8080/api/quants"

RESPONSE

{
  "error": {
    "name": "Error",
    "status": 401,
    "message": "Authorization Required",
    "statusCode": 401,
    "code": "AUTHORIZATION_REQUIRED",
    "stack": "Error: Authorization Required\n    at ...
  }
}

POST error, access didnt get blocked. Not working.

CURL:

curl -X POST --header "Content-Type: application/json" --header "Accept: application/json" -d "{
  \"email\": \"[email protected]\",
  \"password\": \"abcd1234\"
}
" "http://localserver:8080/api/clients"

RESPONSE

{
  "email": "[email protected]",
  "id": "46b258078da5dtg1ji5809ww"
}

Solution

  • Before suggesting solutions, I'll try to explain what's the cause of 'create' (POST) method to not be denied.

    Your client model is a sub-model of Loopback's User built in model.

    Two important things to keep in mind in this case:

    1. ACL's defined in a sub-model are not overriding the base class ACL's, but merged to them.

    2. When a request is checked against ACLs, Loopback's algorithm gives the closer match higher weight. closer match in this specific case is a more specific ACL definition. (reference here)

    Now, Loopback's User model contains the following ACL:

    {
      "principalType": "ROLE",
      "principalId": "$everyone",
      "permission": "ALLOW",
      "property": "create"
    }
    

    Your defined ACL

    {
      "accessType": "*",
      "principalType": "ROLE",
      "principalId": "$everyone",
      "permission": "DENY"
      // no specific property
    }
    

    is less specific, hence not chosen by the algorithm.


    In order to solve the issue, you can:

    1. Add specific ACL for denying creation:

      {
        "principalType": "ROLE",
        "principalId": "$everyone",
        "permission": "DENY",
        "property": "create"
      }
      
    2. Remove the ACL allowing to create from the base User model (very bad solution, but works)