How does auth get applied when the types are seen at multiple levels?

I already have a great answer about how multiple auth rules are handled over on Order of @auth directive Processing - #2 by michaelcompton, but what I want to know specifically here is if a node/Type has to pass the same auth rule multiple times if it is contained at different levels in the graph.

With schema example:

type User @auth(query: { rule: "{$LOGGED_IN: { eq: \"true\"}}" }) {
  username: String! @id
  name: String
}
type Post {
  comments: [Comment]
  author: User
  likedBy: [User]
}
type Comment {
  replies: Comment
  author: User!
}

When I run:

query {
  queryPost {
    author { name }
    comments {
      author { name }
      replies {
        author { name }
      }
    }
    likedBy { name }
  }
}

The type User with the auth rule is found on multiple levels:

  • getPost.author
  • getPost.comments.author
  • getPost.comments.replies.author
  • getPost.likedBy

Does the processing of this query get the data and combines the rules on each level? I will try to explain this in pseudo code:

get Post {
  get author.filter(User auth rules)
  get comments {
    get author.filter(User auth rules)
    get replies {
      get author.filter(User auth rules)
    }
  }
  get likedBy.filter(User auth rules)
}

Or is it processed in a flattened structure (again explaining with pseudo):

filteredUsers as get Users.filter(User auth rules)
get Post {
  get author from filteredUsers
  get comments {
    get author from filteredUsers
    get replies {
      get author from filteredUsers
    }
  }
  getLikeBy from filteredUsers
}

It sort of feels like it processes the former way which would be easier to program but less performant. In my use case I have a deep data query and a type with a lot of rules heavy on query rules is present MANY times through the structure. It feels like it is slow because every use of the type calls a requery of the rules. This may not be the case, just how it feels though.


Personal Context

When I first started learning about graphs, I started at the docs and presentations by neo4j. I don’t have the source at hand anywhere, but when asked if adding more layers of authorization made the database slower, the response was no, it actually made it faster because it then it actually working with a smaller graph instead of a big giant one. It seemed like the auth rules in place actually sort of did a namespacing type feat within the graph so that querying a User type was not applying a set of rules each time, but rather querying only the smaller set of Users that was accessible given the ACL.

I understand that @auth directive is the poor man auth and that the real ACL is an enterprise feature that I have not learned yet (just haven’t seen the need yet). Maybe this is how the ACL feature works in the enterprise version by limiting the size of the graph making it actually faster instead of slower.


Performance Review

I have a query (based on my actual schema not the example above) that returns 25 contacts with what I would consider some basic information to form a table in a UI that then gets paginated by the user. I just looked at an example one and the query took 10 seconds—Not acceptable IMO. A user will get tired of waiting 10 seconds between each paginated table load especially when they are scanning the table for a specific item. Here is an actual extensions response:

extensions: {touched_uids: 3692204,…}
  touched_uids: 3692204
  tracing: {version: 1, startTime: "2020-10-19T03:58:09.492724379Z", endTime: "2020-10-19T03:58:19.57221792Z",…}
    duration: 10079493595
    endTime: "2020-10-19T03:58:19.57221792Z"
    execution: {,…}
      resolvers: [{path: ["queryContact"], parentType: "Query", fieldName: "queryContact", returnType: "[Contact]",…}]
        0: {path: ["queryContact"], parentType: "Query", fieldName: "queryContact", returnType: "[Contact]",…}
          dgraph: [{label: "query", startOffset: 2848749, duration: 10072729121}]
            0: {label: "query", startOffset: 2848749, duration: 10072729121}
              duration: 10072729121
              label: "query"
              startOffset: 2848749
          duration: 10076098192
          fieldName: "queryContact"
          parentType: "Query"
          path: ["queryContact"]
            0: "queryContact"
          returnType: "[Contact]"
          startOffset: 426432
    startTime: "2020-10-19T03:58:09.492724379Z"
    version: 1

If anyone wants to take a closer look at this exact issue, I can work privately with a link and the actual query and schema used. It has sensitive data so I cannot post it publicly.

@pawan, can you confirm which way auth gets applied at multiple levels? I may need to simplify my auth rules to get faster results because this is really slowing down my results. Sorry, I am not familiar enough with Go to figure out this for myself from the repo.

It’s applied similar to this approach. Note this should result in a smaller graph as at every level before applying the auth rules we have already reduced the input. That is get only authors for a post or only get authors of certain comments and then apply the auth rules.

Sure, please share that in a DM with me and @abhimanyusinghgaur and we’ll be happy to see what is causing this slowdown and how can we optimize it.

1 Like