Token authentication with React and Apollo Client— a custom hook example

Antoine Sauvage
OVRSEA
Published in
4 min readApr 5, 2020

Authentication is often a pain for beginners (and experimented!) developers.

The goal of this article is to show a basic authentication system on the client side (a React App) with Apollo Client.

Disclaimer : this article does not cover authentication on the backend!

In this article we will cover

  • managing your authentication token with react-cookies
  • passing your auth token in your headers
  • login & logout
  • encapsulating the logic in reusable hooks

As backend, we will use Strapi, which provides a ready to use auth system to test our frontend. You can use any backend that works with a token.

The full repo with Strapi and React is here : https://github.com/ovrsea/react-apollo-strapi-auth-example

If you want to test it, go in /backend, do yarn install && yarn start , and in /frontend, do yarn install && yarn start

Global architecture

Below is shown the architecture that we want to implement:

There are two “authentication data”: the auth token itself and the user data. The auth token authenticates the queries, and is thus mandatory to consider the user authenticated. The user data is a good way to “check” the authentication token : if it fails, the user has to re-login for example.

We want to give access to our App if and only if we have a token and the user query works with this token.

Managing your auth token

The first step is to manage our auth token. In this example, our auth token is stored in the cookies of the browser. It allows to persist the session even if the user leaves and comes back.

First, we have to wrap our App with a CookiesProvider

App.js

Then, we create a hook that allows to:

  • get the token
  • save the token
  • remove the token

Encapsulating in a custom hook will allow us to access our token easily across our App. Here is our code:

auth.js

Passing your auth token to your queries

Once we have a token (which we don’t have for now! 😁), we have to put the token in the headers of our requests. A classic authentication system is to put the token in the “authorization” header, under the form "Bearer <myToken>"

In our case, we have to use an Apollo Link in order to do that. A “link” is a piece of software that “modifies” the request and passes it along. For example, it can update headers, log errors, etc.

Below is the full code to configure our Apollo Client:

What do we have here ?

First, we have the normal configuration of an Apollo Client : http-link + cache.

Then, we created an authMiddleware that “injects” the token in our authorization header. That’s it!

Getting an auth token

At this point, if we have an auth token, we can query our backend. The thing is, we don’t have one!

In order to fetch an auth token, we have to send our login and password to the server, that will respond with a token that we have to save for further use. This is done by using the “login” mutation in our case :

What’s interesting here is that we composed hooks. Remember our useAuthToken hook? We have now created a hook that combines useMutation and useAuthToken. This hook calls the login mutation, and if it succeeds, saves the results in our token store (the cookies!)

We can now call this hook from a basic form (using react-hook-form here) :

Fetching the user and protecting our App

As stated before, we also need to fetch our user once we have the token stored in our cookies. Below is a code that works for a Strapi backend :

Everything is in now in place, all we have to do is to decide what to serve : authentication form or protected page? In this example, we created an AuthGate, in charge of deciding :

We are now all set!

Going further : logout

Logging out is now super easy, we will create a custom hook again. Logging out will:

  • clear apollo client cache
  • remove the authToken from the cookies

We can use it in our PrivatePage for example:

Going further : remove the token before login

Sometimes, having a token in the headers for the login mutation can trigger bugs (this is the case for Strapi, if the token is invalid for example). To avoid this, we can remove the token before triggering the mutation. We slightly adapt our login hook:

You can also go further by:

  • not re-instantiating an Apollo Client every time App renders(use useCallback or useMemo)
  • logging out on the server too
  • etc.

Overall, authentication is a never ending topic. This article is a good starting point for a React + Apollo web app, but let us know in the comments how you improved this basic schema and your use case!

Happy coding!

Interesting links on the internet :

https://kentcdodds.com/blog/authentication-in-react-applications

--

--