Skip to content

[Bug]: Cannot filter with custom role (access forbidden...) #2115

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
1 task done
lionelschiepers opened this issue Mar 19, 2024 · 3 comments
Open
1 task done

[Bug]: Cannot filter with custom role (access forbidden...) #2115

lionelschiepers opened this issue Mar 19, 2024 · 3 comments
Labels
cri Customer Reported issue enhancement New feature or request

Comments

@lionelschiepers
Copy link

lionelschiepers commented Mar 19, 2024

What happened?

Hi, I have a config file that is defining a custom role (let say role-a) but I can't filter anonymous entites when that role is used. I'm receiving this error:

{
  "errors": [
    {
      "message": "Access forbidden to a field referenced in the filter.",
      "extensions": {
        "code": "AuthorizationCheckFailed"
      }
    }
  ]
}

To reproduce the problem, you have to query the server with X-MS-API-ROLE = role-a + a principal that defines that role. You receive that error when you are filtering an anonymous entity.

When I look at the code, the authenticated role derives from anonymous and a custom role derives from authenticated role.

I think that the problem is in AuthorizationResolver near line 135 in the method AreColumnsAllowedForOperation. When a custom role is used and that role is not defined at the entity level, the method should check the role the custom role is inheriting from, authenticated in this case.

The test should looks like:

        RoleMetadata? roleMetadata;
        if (!EntityPermissionsMap[entityName].RoleToOperationMap.TryGetValue(roleName, out roleMetadata) && roleMetadata is null)
        {
            if (ROLE_ANONYMOUS.Equals(roleName, StringComparison.OrdinalIgnoreCase) ||
                ROLE_AUTHENTICATED.Equals(roleName, StringComparison.OrdinalIgnoreCase))
            {
                return false;
            }
            // roleName is a custom role and derives from authenticated role. Let's try with authenticated role.
            if (!EntityPermissionsMap[entityName].RoleToOperationMap.TryGetValue(ROLE_AUTHENTICATED, out roleMetadata) && roleMetadata is null)
            {
                return false;
            }
        }

instead of

        if (!EntityPermissionsMap[entityName].RoleToOperationMap.TryGetValue(roleName, out RoleMetadata? roleMetadata) && roleMetadata is null)
        {
            return false;
        }

a work around could be to define the custom role in all entities but it's not possible to do that with the cli. You can only set one single permission by entity.

another work around could be to update the EntityPermissionsMap collections to include all custom roles defined in the configuration file and derive them from the authenticated role like the authenticated role is copied from the anonymous role (method SetEntityPermissionMap in AuthorizationResolver near line 357 when calling CopyOverPermissionsFromAnonymousToAuthenticatedRole).

I tried to do a pull request but I don't have a write access to the repository.

Is there any chance to find a correction for this?

Kind regards,
Lionel Schiepers.

Version

0.10.23

What database are you using?

Azure SQL

What hosting model are you using?

Local (including CLI), AppService, Static Web Apps (SWA), Container Apps

Which API approach are you accessing DAB through?

GraphQL

Relevant log output

{
  "errors": [
    {
      "message": "Access forbidden to a field referenced in the filter.",
      "extensions": {
        "code": "AuthorizationCheckFailed"
      }
    }
  ]
}

Code of Conduct

  • I agree to follow this project's Code of Conduct
@lionelschiepers lionelschiepers added bug Something isn't working triage issues to be triaged labels Mar 19, 2024
@seantleonard seantleonard added enhancement New feature or request cri Customer Reported issue and removed bug Something isn't working triage issues to be triaged labels Mar 19, 2024
@seantleonard
Copy link
Contributor

When you are adding a filter to your GraphQL request, you will be subject to the permissions set for the given entity. Your example role, role-A, must be defined on the entity you are querying against.

Note that DAB does not perform role inheritance. The entity definition in the dab-config.json must include a permission which defines the role role-A and the associated permissions. Based on that requirement, I'm classifying this as a feature request for now.

To help us best understand your ask: please add a minimum reproducible example with:

  1. Applicable dab-config.json (specifically, the configuration for your target entity)
  2. Database schema (specific table/sample data)
  3. Applicable GraphQL request (You already noted a x-ms-api-role header value)

@lionelschiepers
Copy link
Author

lionelschiepers commented Mar 19, 2024

Hi, the actual behavior is not consistent.

if you have entity-a that only define one permission: anonymous read access. Why can you query that entity with role-a even if that role is not defined at the entity level? If you have access to the fields of that entity from role-a, why can't you filter on the fields you have access to?

I'm not opposed to define role-a for all entities in our environment but everything is automated with dab cli and the cli doesn't permits to define multiple permissions by entity. Do you have any advise about how to handle this?

@lionelschiepers
Copy link
Author

lionelschiepers commented Mar 19, 2024

Here is an example. The attributes entity below only defines the anonymous role.
Why can I query the attributes entity and read the values of all fields when the query is executing under the role-a but I can't filter on the same fields? The engine should have a consistent behavior in term of access permission. If I have access to the fields I should be able to filter on them.

    "Attributes": {
      "source": {
        "object": "xxx",
        "type": "table",
        "key-fields": [
          "id"
        ]
      },
...
      "permissions": [
        {
          "role": "anonymous",
          "actions": [
            {
              "action": "read",
            }
          ]
        }

this kind of query works under role-a even if attributes doesn't define any access for role-a. Is it the expected behavior?

query
{
  attributes
  {
    items
    {
      id
    }
  }
}

my X-MS-CLIENT-PRINCIPAL looks like this:

{
  "userId": "xxx",
  "userRoles": [
    "anonymous",
    "authenticated",
    "role-a"
  ],
  "identityProvider": "xxx"
}

and X-MS-API-ROLE = role-a.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cri Customer Reported issue enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants