How to write @auth incase of user role claim in JWT has a array format

Hi there,

I have the following schema in dgraph

type Todo {
    id: ID!
    text: String! @search(by: [term])
    owner: String!
}

I wanted to implement Role-Based Access control (RBAC) using the JWT token. My sample JWT token with role looks like below

{
  "http://abc.xyz.com//roles": [
    "admin",
    "superadmin"
  ],
  "nickname": "abc",
  "name": "abc@gmail.com",
  "picture": "",
  "updated_at": "2020-09-08T12:59:14.801Z",
  "email": "abc@gmail.com",
  "email_verified": false,
  "iss": "https://xxx.us.auth0.com/"
}

I know that I have use @auth directive in the schema to implement the authorization in the schema. I case if my claim contains “isAdmin”: “true” claim, I can write @auth in the below format

type Todo @auth(
    delete: { rule:  "{$isAdmin: { eq: \"true\" } }" },
) {
    id: ID!
    text: String! @search(by: [term])
    owner: String!
}

But in the given JWT sample above roles are in the array format. My requirement is to allow delete only if the user role is ‘admin’ or ‘superadmin’. My question here is how I write the @auth directive to check, in the above JWT whether the claim “http://abc.xyz.com//roles” contains ‘admin’ or ‘superadmin’. Maybe I need to write rule using “in” operator. But i don’t know how to do it. Can anybody help me to write @auth directive for my requirement? Thanks in advance.

Hi @sarankrishna, I assume you have added the # Dgraph.Authorization … line at the bottom of schema.

I don’t know how to do this. But please see if this helps. I have this JWT

"https://dgraph.io/jwt/claims": {
    "USER": "xxx@gmail.com",
    "ROLE": "ADMIN"
  },
  "given_name": "xxx",
  "family_name": "xx",
  "nickname": "xxx",
  "name": "xxx",

And I can use it in this way. Please see if you can do something similar.
Tagging @abhimanyusinghgaur if he can provide better way.

Not currently possible using arrays in Role Based Access Control.

Here was a related discussion:

That was about Booleans, but arrays are not supported either. I know I saw that somewhere here in the forum, just can’t find it right now. It might have been when @gja initially walked me through it that I picked that up.

Anyways, the only way to accomplish this right now would be to convert that array to single properties:

{
  "http://abc.xyz.com//admin": "true",
  "http://abc.xyz.com//superadmin": "true",
  "nickname": "abc",
  "name": "abc@gmail.com",
  "picture": "",
  "updated_at": "2020-09-08T12:59:14.801Z",
  "email": "abc@gmail.com",
  "email_verified": false,
  "iss": "https://xxx.us.auth0.com/"
}

Not sure though that you were not trying to use http://abc.xyz.com//roles as the claims portion of your JWT. If that was the case then it would need to look like:

{
  "http://abc.xyz.com/claims": {
    "isAdmin": "true",
    "isSuperAdmin": "true",
  },
  "nickname": "abc",
  "name": "abc@gmail.com",
  "picture": "",
  "updated_at": "2020-09-08T12:59:14.801Z",
  "email": "abc@gmail.com",
  "email_verified": false,
  "iss": "https://xxx.us.auth0.com/"
}
2 Likes

@Naman Thanks for the response. I already added # Dgraph.Authorization line in the bottom of the schema. But my question was how to write the query/add/delete/update condtion when JWT contains the arrary of roles.

@amaster507 Thanks for the response. I did exactly the same as you mentioned above(2nd way).

Currently, the only way to achieve this is to break the array into single values as @amaster507 mentioned. But we will add support for arrays in RBAC rule in the upcoming release.

1 Like

Has this landed in production yet? If not, will it come in November?

I have marked this issue as accepted. It won’t be part of the 20.11 release but we’ll take it up in the one after that.

2 Likes

@pawan I saw that support has been added for the array logic in the @auth directives on master - is there a way to do the reverse yet where an array is provided in the claims and one/more values are defined in the @auth definition that must be matched to?

1 Like

Hi @forstmeier,
We did add the reverse support. You can check the example test case.

In short, both claims in JWT Token or auth rules can be array. Important thing to note is the equality check. Equal checks behave on the same line as graphql filters. So for example, say claims are of value [A, B, C] and Auth Rule says [filter: in][C, D, E]. Then C being the match, it will return true. Do let us know if you face any issues :slight_smile:

2 Likes

@aman-bansal, can you please provide an example in the form of a GraphQL rule? I cannot figure out how to use the filter operation with @auth ROLE claim.

You are probably looking for this syntax:

Basically use the in logic. Which I believe from this discussions can be used with the array being the array from a JWT or from a static array in the rule:

{ $SINGLE_ROLE: { in:  [\"USER\", \"ADMIN\"] } }
{ \"ADMIN\": { in: $ROLE_ARRAY } }
1 Like

We should continue this discussion in the thread dedicated to operating on the $ROLE array, since it seems like it may actually behave differently than the $USER claim from the tests.