Easy peasy GraphQL authentication and authorization using Schema Directives

Written by martinhaagensli | Published 2018/07/01
Tech Story Tags: javascript | graphql | schema-directives | graphql-authentication | graphql-authorization

TLDRvia the TL;DR App

You can find the repo for this tutorial here;https://github.com/mhaagens/graphl_authentication_authorization

Getting started

We’ll be using Apollo’s amazing GraphQL tools to set up our GraphQL-server and create our schema. First we need to install some dependencies for our project;

First, let’s create our package.json;

npm init -y

Then let’s install our dependencies;

npm install apollo-server graphql lodash

Next we’re going to install nodemon so we can reload our server automatically on changes. If you want to learn how to Hot Reload your server using Webpack and ES6 modules — without restarting the server — you can check out another tutorial of mine here; https://hackernoon.com/hot-reload-all-the-things-ec0fed8ab0

npm install nodemon --save-dev

Finally, let’s add our start script to package.json;

'scripts': {'start': 'nodemon ./src/app.js'},

Setting up application structure

Recreate this tree structure in the folder where you’ve set up package.json and your node_modules;

src/directives/- requireAuthDirective.jsmodels/- post.js

  • app.js
  • schema.jsnode_modules/package.json

Now that we have our structure, let’s paste in some boilerplate code to get us started;

src/app.js

This code sets up our GraphQL server using the amazing Apollo Server 2.0 🔥.We import our type definitions, resolvers and schema directives and finally we hard code a user on the request property of the server context object — in production you would need to set up a database with password hashing, JWT or session cookie middleware etc. — but to keep the focus on just the GraphQL part we’re skipping all of that and just hard coding a user for now. We also add our requireAuthDirective (which we’ll create in a bit) to our schemaDirectives .

src/schema.js

Here we define our schema and extend our root type definition with our Post type definitions and then merge the Post resolvers with the root resolver. We’ll create the Post type definitions and resolvers in the next step. We also create the Role enum for our schema directive.

src/models/post.js

Now that we have our schema, let’s create our Post type definitions and resolvers. We’re just hard coding some posts to return and then we extend the Root query with the query resolver for posts which will return all our posts — assuming you’re authenticated and authorized.

Notice the @requireAuth directive after the posts query definition.This is how we tell our schema to use the directive for the field definition.

src/directives/requireAuthDirective.js

This is where we define our rules for the schema directive.We create a directive which extends “SchemaDirectiveVisitor” from apollo-server. We check that a user exists on our context.req object, and if a role is specified that the role matches that of the user. If it does we resolve the field, if not we throw an AuthenticationError.

Let’s try it out!

Run npm start and go to http://localhost:3000/.You should now see the GraphQL Playground where you can run queries against your schema.

Run a query against posts and it should return the postssince we’re “logged in” with our hardcoded user;

But what if we want to require a role to access the posts?Our user is hardcoded with the USER role, so let’s require the ADMIN role to access the post.

Open src/models/post.js and change the @requireAuth directive to @requireAuth(role: ADMIN). Run the query again in the playground and you should now be getting an AuthenticationError.

Finally, let’s remove the user entirely from our server context to check that you need to be signed in to access the posts.

Open src/app.js and remove the context object from the server, like this;

You should now be getting another AuthenticationError telling you that you need to be signed in to view the resource;

Wrap up

So that’s it. This is a simple introduction to using Schema Directives for authentication and authorization. Now, please don’t go using this code in production — there are probably a lot more checks to be done and of course you need to implement either session cookies or JWTs securely to get this working properly — but I hope you’re a little further a long in implementing proper auth in your GraphQL web application after reading this article!

For more articles on web dev, GraphQL and Javascript, follow me on Twitter;https://twitter.com/mhaagens

Further reading;https://www.apollographql.com/docs/graphql-tools/schema-directives.html

Thanks

Thanks to **@**jbaxleyiii for all the helping me figure out how to implement Schema Directives and the Apollo team for their amazing work!


Published by HackerNoon on 2018/07/01