DEV Community

Cover image for Why is GraphQL TokenAuth is Using Mutation Instead of Query?
Anzhari Purnomo
Anzhari Purnomo

Posted on

Why is GraphQL TokenAuth is Using Mutation Instead of Query?

Adding more context into the question, what confuses me are why some library (e.g. Django GraphQL JWT and Apollo Server) implement the TokenAuth as a mutation (mutation as in GraphQL mutation operation) instead of a GraphQL query operation.

What I understand from the term is "mutation" means change in the data. A TokenAuth operation to generate JWT shouldn't mutate any data, only checking the credentials provided whether it is valid or not, which should be more appropriate to use "query" operation instead.

Found the answer here: https://stackoverflow.com/questions/50189364/shouldnt-the-login-be-a-query-in-graphql

An excerpt:

In the context of that example, login should be a Query instead of a Mutation assuming its resolver has no side-effects, at least according to the spec. However, there's a couple of reasons you probably won't see that done in the wild:

  • If you're implementing authentication, you'll probably want to log your users' account activity, either by maintaining some data about login/logout events or at least including some sort of "last login" field on the account's record. Modifying that data would be a side effect.
  • A convention has evolved that treats any operations that result from user actions as Mutations, regardless of side-effects. You see this with react-apollo, for example, where useQuery fires the associated query on mount, while useMutation only provides a function that can be called to fire that query. If you're planning on using Apollo client-side, it's worthwhile to consider those sort of client features when designing your schema.
  • Mutations are ran sequentially, while queries are ran simultaneously. That means it'd be foreseeable to fire a login mutation and one or more other mutations after it within the same call, allowing you to utilize an authenticated context for the subsequent calls. The same could not be said for queries -- if login is a query and you include other queries with it in the same operation, they will all begin resolving at the same time.

Outside of how they're executed (sequentially vs simultaneously), on the server-side, queries and mutations are effectively interchangeable. You could have queries with side-effects and mutations with no side effects. You probably should stick with conventions, but I think sometimes there's valid reasons where you may have to throw those conventions out the window.

Also, this stackoverflow post outlines that GraphQL mutation must be executed sequentially, as described by GraphQL specification:

If the operation is a mutation, the result of the operation is the result of executing the mutation’s top level selection set on the mutation root object type. This selection set should be executed serially.
It is expected that the top level fields in a mutation operation perform side‐effects on the underlying data system. Serial execution of the provided mutations ensures against race conditions during these side‐effects.

Top comments (0)