Conflict between policies - field based permission

I am using docker image tykio/tyk-gateway:v5.0.0 and testing the graphql policies config. I would like to create 2 policies article-admin-policy and publisher-admin-policy for accessing the UDG queries

type Query {
  articles: [Article!]!
  publishers: [Publisher!]!
}

accordingly.

I am using jwt “scope_to_policy” in api def json and here’s the policy json:

{
  "article-admin-policy": {
    "id": "article-admin-policy",
    "rate": 1000,
    "per": 1,
    "quota_max": 100,
    "quota_renewal_rate": 60,
    "max_query_depth": 5,
    "access_rights": {
      "a16771d0-b43a-4469-a241-2a6fec0bfa0f": {
        "api_id": "a16771d0-b43a-4469-a241-2a6fec0bfa0f",
        "versions": [
          "Default"
        ],
        "allowed_types": [
          {
            "name": "Query",
            "fields": ["articles"]
          },
          {
            "name": "Article",
            "fields": ["*"]
          }
        ],
        "restricted_types": []
      }
    },
    "org_id": "org",
    "hmac_enabled": false,
    "active": true
  },
  "publisher-admin-policy": {
    "id": "publisher-admin-policy",
    "rate": 1000,
    "per": 1,
    "quota_max": 100,
    "quota_renewal_rate": 60,
    "max_query_depth": 5,
    "access_rights": {
      "a16771d0-b43a-4469-a241-2a6fec0bfa0f": {
        "api_id": "a16771d0-b43a-4469-a241-2a6fec0bfa0f",
        "versions": [
          "Default"
        ],
        "allowed_types": [
          {
            "name": "Query",
            "fields": ["publishers"]
          },
          {
            "name": "Publisher",
            "fields": ["*"]
          }
        ],
        "restricted_types": []
      }
    },
    "org_id": "org",
    "hmac_enabled": false,
    "active": true
  }
}

Expected Result:
when a user have both scopes, both of the queries can be access.

Actual Result:
when a user have either one scope of both scopes, none of the query can be access.

field: publishers is restricted on type: Query
field: articles is restricted on type: Query

If I merge both policy into a single policy with all allowed_types configuration, it works. Am I missing some configuration or using an outdated docker image?

Hi @Allen_Wong and welcome to the community.

First of all you are not using an outdated docker image.

I think your configuration might be the problem. You mentioned, you are using jwt_scope_to_policy_mapping, so I assume you are using JWT authentication. Could you review our documentation on JWT scope to policy mapping support.

You also say that when you merge them into a single policy it works. Are there changes to your API definition and policy definition when you do? Maybe sharing your API definition might help.

Edit
Linked the wrong doc initially. Modified it now to point to the correct endpoint

Thank you for the reply. I read the document and found the below note.

Several scopes in JWT claim will lead to have several policies applied to a key. In this case all policies should have "per_api" set to true and shouldn’t have the same API ID in access rights. I.e. if claim with scopes contains value "admin developer" then two policies "59672779fa4387000129507d" and "53222349fa4387004324324e" will be applied to a key (with using our example config above).

let say I would like to apply several scope like “admin developer” to a key, so there will be 2 policies admin-policy and developer-policy defining different allowed_types for same UDG under access_rights session, how could I perform that without using same UDG API_ID?

It would be complex on a UDG API definition as your UDG design could be simple or very elaborate.

With REST it’s a bit technical and involves making a keyless API serve as the proxy. Then URL rewrite to a specific path that is mapped to separate internal API definitions with the access.

To be honest, the easiest way would be to map a combined scope to a unique policy e.g. admin-developer

I have tried using ProxyOnly instead of UDG, issue still exists.

Case 1
policy1: allow access queryA & queryB
user with policy1: can access queryA and queryB (OK)

Case 2
policy1: allow access queryA
policy2: allow access queryB
user with policy1: can access queryA, cannot access queryB (OK)
user with policy1 & policy2: cannot access queryA nor queryB (Unexpected)

Case 3
policy1: allow access queryA, queryB
policy2: allow access queryB
user with policy1: cannot access queryA nor queryB (Unexpected)
user with policy1 & policy2: cannot access queryA nor queryB (Unexpected)

To summarize, it appears that field-based permissions can only have one combined scope for one User-Defined Guard (UDG) or GraphQL Proxy. Otherwise, would it mean to I have to separate the GraphQL API definition into multiple definitions? From my perspective, it doesn’t seem logical to define GraphQL field-based permissions that cannot be merged across policies.

As you’ve found out, the issue would still exist even if you changed execution modes. The merge issue comes from the design of policies and keys. The limitation didn’t occur from the GraphQL design.

I’m quite surprised that Case 3 user with policy1: cannot access queryA nor queryB (Unexpected) didn’t work. Can you share your key and policy definition?

To summarize, it appears that field-based permissions can only have one combined scope for one User-Defined Guard (UDG) or GraphQL Proxy. Otherwise, would it mean to I have to separate the GraphQL API definition into multiple definitions?

Don’t quite understand what the former statement means but the latter is correct. This can be complex and is why I suggested using a scope mapped to a policy that contains the access_rights and field_based_permissions