Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I implement auth directive for mutations with Apollo?

I am trying to set up an Apollo backend for a project I'm working on, where I'm attempting to implement schema directives. However, I am not able to add my schema directive to mutations. So to my main question: How do I implement an auth directive for mutations?

I have added @auth(requires: ADMIN) to the end of my users query, which is working fine. Apollo will then require a bearer token with admin access for performing the users query.

extend type Query {
    user(id: ID!): User
    users: [User!]! @auth(requires: ADMIN)
}

When I tried to do it in the same way for the editMyUser mutation, the auth directive seems to be enforced for all the mutations, instead of just the one I wanted. Even the signUp mutation will give "not authorized" error, when I add the @auth part to the editMyUser mutation. Even though there is no relation between them.

The role field which is supposed to be passed to the auth directive when invoked is logging out empty.

extend type Mutation {
    signUp(
        username: String!
        firstName: String
        lastName: String
        password: String!
        isAdmin: Boolean
        isActive: Boolean): User!
    login(
        username: String!
        password: String!): User!
    editMyUser(
        id: ID!
        firstName: String
        lastName: String
        password: String): User! @auth(requires: USER)
    adminEditUser(
        id: ID!
        firstName: String
        lastName: String
        password: String
        isActive: Boolean
        isAdmin: Boolean
        isBanned: Boolean): User!
}

This is how I implemented the schema directive

export default gql`
directive @auth(requires: Role = ADMIN) on OBJECT | FIELD_DEFINITION

enum Role {
    ADMIN
    USER
}

https://github.com/jwhenshaw/graphql-directives-auth This is the Auth Directive I've implemented in my code for reference.

So to summarise, when I implement auth directives for mutations they are implemented for all mutations, instead of just the one, and it is not even working correctly, as roles are not passed on to the directive.

I would love to get some help with this. Thanks!

like image 666
Jørgen Vik Avatar asked Jan 02 '19 10:01

Jørgen Vik


1 Answers

Within that repo the AuthDirective class passes the objectType of the field being wrapped into the ensureFieldWrapped method. What this means is that for your example where you are assigning the directive directly onto a field, editMyUser, on the object of Mutation the method is wrapping all the children of Mutation (I believe the same should be true for your Queries as well actually).

So, within the example repo, this is fine as we have an Object type User and we wrap it and its fields. However, if you do not wish to do this we can alter the AuthDirective class to wrap just the field it is on.

I have done this and pushed to the repo, https://github.com/jwhenshaw/graphql-directives-auth, where you can see there is now a FieldAuthDirective and a ObjectAuthDirective. I still need to clean the code a bit but pushed a working example and left some logs to help highlight the differences. You can view it here https://qzj70qn2mj.sse.codesandbox.io/ if you don't fancy running it locally.

Hope this helps, let me know if I need to elaborate some more.

like image 61
James Henshaw Avatar answered Oct 19 '22 23:10

James Henshaw