@auth directive on $ROLE array for Auth0 compatibility

[v21.03] Consider Auth0 JWT structure where ROLE claim is an array:

{
  "https://dgraph.io/jwt/claims": {
    "USER": "ctjlewis",
    "ROLE": [
      "Admin",
      ...
    ]
  },
  ...
}

I have tried the following form for the add rule but the request still fails unless I comment it out:

add: {
  rule:  "{$ROLE: { eq: \"Admin\" } }"
}

Is there a recommended approach for using the @auth directive and array ROLE JWT claim? It doesn’t seem immediately obvious to me if this is possible, and Auth0 does not let users configure how the claim is declared.

This seems to be possible given the discussion in the following thread, but I am struggling to find a code example:

The code example for this use case should be added to the article on Auth0 integration also:

https://dgraph.io/docs/graphql/todo-app-tutorial/todo-auth0-jwt/

With:

add: {
  rule:  "{ \"Admin\": { in: $ROLE } }"
}

I get:

{"errors":[{"message":"resolving updateGQLSchema failed because Type User: @auth: `\"Admin\"` is not a valid GraphQL variable. (Locations: [{Line: 3, Column: 4}])","extensions":{"code":"Error"}}]}

The following works:

rule:  "{ $ROLE: { in: [ \"Admin\" ] } }"

But that’s not what we want, because $ROLE is an array. You’re right that this should probably be what works, but it doesn’t seem to be.

Sorry, I didn’t test this, just assume that is what the reverse syntax would be. Hmm, thinking of how this would look like in reverse if that didn’t work.

1 Like

No worries at all, I had not actually tied that pattern despite trying like 20 others. I really thought that one was it, but it seems like the rule only accepts a variable for that token { $ROLE: ... }, and won’t accept a string, but there’s no other way to say “is this literal in this array?”.

If we could find any documentation (external/internal) on the structure of the rule parameter, we could maybe get a little more context if nothing seems obvious.

Can you NOT do either either of these?

rule : "{ $ROLE: { has: [ \"Admin\" ] } }"

or

rule: "{ \"Admin\": { in: $ROLE } }"

If not, these should definitely be a Feature Request.

J

2 Likes

So what about:

{ $ROLE_ARRAY: { in: [\"ADMIN\"] } }
  1. Parses, but returns null (here, as an add rule for addUser) and operation does not complete:

    rule:  "{ $ROLE: { in: [\"Admin\"] } }"
    
  2. Schema update fails for:

    rule : "{ $ROLE: { has: [ \"Admin\" ] } }"
    

    With error message:

    updateGQLSchema failed because Type User: @auth: `has` operator is not supported. (Locations: [{Line: 3, Column: 4}])
    
  3. Schema update fails for:

    rule: "{ \"Admin\": { in: $ROLE } }"
    

    With error message (string isn’t a variable):

    updateGQLSchema failed because Type User: @auth: `\"Admin\"` is not a valid GraphQL variable. (Locations: [{Line: 3, Column: 4}
    

And I would work around by just doing { $ROLE: { eq: [ \"Admin\" ] } } but you get an error that eq is not supported with arrays.

1 Like

But categorized Dgraph Cloud which I think is still ~v20.11.X

Silly question, but are you sure you are on v21.03?? Look in the settings page of Dgraph Cloud for your exact version.

Not in Dgraph Cloud right now, I’m developing locally on 21.03 because GraphQL introspection is broken on 20.x. See:

We were told Dgraph Cloud will ship 21.03 within a few weeks, which we would hold off shipping until then, or alternatively, if there were more delays, we would set up a dedicated instance or set up a cluster in AWS.

But basically yes, 21.03, we will be shipping 21.03 or later.

1 Like

I recategorized. Sorry I can’t help much more tonight. Official @graphql support on Monday probably has the answer off the top of their head.

I don’t have systems setup locally to run and test 21.03 to try some other ideas and retry some of the above with fresh eyes.

1 Like

No worries, I appreciate your responsiveness. My timeframe is a few weeks to a month or two.

We definitely can’t launch on Dgraph without Auth0 integration though, so I will be contributing on this issue as well once I get a better understanding of what’s going on, if that’s welcome. Any documentation on the rule parameter and where it’s specified in the codebase would rock, once someone gets a chance, otherwise I will try to find it myself within a few days.

According to the comments on this line the eq and in logic should both work given an array in JWT

1 Like

That naively looks like it expects $USER to be a scalar, and implies it will soon support an array as a value for eq (which was added below that).

I will add more tests in there that directly support ROLE claims as arrays, basically just copying this example but with a mixture of Admin/User/Moderator combinations as an array value in ROLE. This will add test coverage for any conceivable RBAC configuration really, where right now it would seem to be limited to a single value (maybe more with JSON encoding? is that the recommended approach?)

Here is the functions that run these rules:

I try to make sense of Golang, but don’t dare say I understand it enough yet to point to the exact spot where the array in the value gets tested against a string. This is as close as I can get you.

The comment here on line 118 makes it pretty clear again that the equal should work to test for a single value exists in ROLE array

1 Like

Agreed, that comment seems to unambiguously say that it intends to make in op “just work”, where [1, 2, 3]: { in: { [false, 1, false, ...] } matches, i.e., it just looks for one mutual member. It also seems to indicate this should hold for eq.

Would next see if there’s test coverage for it and add if not. But I am also a JS/TS guy, not very familiar with Go. I will take a look over the coming days.

1 Like