In this article I will show you an example how to implement authentication on schema generation level, middlewares and access control.
If you are already familiar with GraphQL and Express and have some experience in API development, this article is for you.
I will create one small library application.
This application will have two types of data: Users and Books.
In order to get list of books or get single book, user should be authenticated and have “View” role.
If user wants to delete book from system, he will need to be authenticated and have “View” and “Delete” roles.
A user authentication policy is a process used to verify that someone who is attempting to gain access to services and applications is who they claim to be.
Authorization is a security mechanism to determine access levels or user/client privileges related to system resources including files, services, computer programs, data and application features. This is the process of granting or denying access to a network resource which allows the user access to various resources based on the user’s identity.
I will not describe and show process of configuring Typescript, Nodemon and writing some things like interfaces. You will be able to take a look at whole app code on Github repository.
Link to repo will be at the end of this article.
If you take a look inside graphql folder , you will notice two folders: authorized & unauthorized. I did a physical split of resolvers, queries, types and mutations for authorized and unauthorized schema.
Based on user authentication status, our app will know which kind of schema should be served to end user.
With this split we got one more security level.
When user which is not authenticated obtain GraphQL schema from server, he will not be able to see list of queries and mutations which require authentication.
I will create resolver register where we will be able to control which resolvers should be included in authorized and unauthorized schemas.
Now I will setup Authentication and Access control middlewares.
Authentication middleware will be running on entire GraphQL endpoint.
Access control middleware will be running on resolvers level.
Now I will setup helper for running middle-wares on resolver level.
NOTE: In real world scenario I would use real database and real authentication standard such as JWT. But in this article I’m faking the DB and authentication system.
In this fake DB, user objects have assigned different roles and tokens which will be used for authentication and authorization.
Tokens will simulate bearer tokens.
Below you can see in book resolver how to use middlewares on resolver level:
Now let’s wrap this all:
Let’s run server with npm start command
When server is started, let’s try obtaining schema as unauthenticated user from Insomnia.
As you can see above, as unauthenticated user we are only able to use login query.
Let’s log in and try obtaining schema as authenticated user.
After successful login we got hash that should be sent in request as value of Authorization header value.
As currently logged in user have only “View” role, let’s try obtaining list of all books.
Now let’s try deleting book as a user who don’t have required permission for that action.
As expected server did not let us perform delete action without required permission.
I will log in as second user (firstname.lastname@example.org) who is permitted, replace Authorization header hash and try deleting book.
App is working.
We successfully deleted a book as a permitted user!
Thanks for reading !