This tutorial is out of date and no longer maintained.
Email, Facebook, Google, Twitter, Github are all possible options for authenticating users in your web apps. Apps built with React and GraphQL are no less candidates for such authentications.
In this article, you will learn how to add varieties of authentication providers to a GraphQL app using:
We will also learn how to protect React routes from being accessed if the user fails to be authenticated by our authentication server.
The plan is to have a React project setup. In the same directory where the React project is set up, we can configure a Graphcool server and tell our project how we want our server to behave. Start with installing the create-react-app
and graphcool-framework
CLI tools:
Then use the React CLI tool to scaffold a new React app:
Create the Graphcool server by moving into the React app you just created and running the Graphcool init command:
You need both public and protected routes:
Create a containers
folder and add home.js
, profile.js
, admin.js
, and about.js
as files to represent each of these routes.
Home.js
About.js
Profile.js
Admin.js
Each of the pages imports and uses Hero
to display a landing hero message. Create a components
folder and create a Hero.js
file with the following:
You can add the navigation component as nav.js
in the components folder as well. Before we do that, we need to set up routing for the React app and have the pages exposed as routes.
Start with installing the React Router library:
Next, provide the router to the App through the index.js
entry file:
Then configure the routes in the App component:
Back to the navigation component (nav.js
), we want to use the Link
component from react-router-dom
to provision navigation:
Next, create a Graphcool Server
Let’s step away from the client app for a second and get back to the Graphcool server we created earlier. Graphcool has a serverless function concept that allows you to extend the functionalities of your server. This feature can be used to achieve a lot of 3rd party integrations including authentication.
Some functions for such integrations have been pre-packaged for you so you don’t have to create them from scratch. You only need to install the template, uncomment some configurations and types, then update or tweak the code as you wish.
Let’s add the Auth0 template. Make sure you are in the server
folder and run the following:
This will create an auth0
folder in server/src
. This folder contains both the function logic, types, and the mutation definition that triggers this function.
Next, you need to create an Auth0 API and then add the API’s configuration to your server. Create an account first, then create a new API from your API dashboard. You can name the API whatever you like. Provide an identifier that is unique to all your existing APIs.
Uncomment the template configuration in server/src/graphcool.yml
and update it to look like this:
AUTH0_DOMAIN
and AUTH0_API_IDENTIFIER
will be exposed on process.env
in your function as environmental variables.
The template command also generates a type in server/src/types.graphql
. It’s commented out by default. You need to uncomment the following:
You need to remove the User
type that was generated when the server was created so that this auth User
type can replace it.
Next, you need to make some tweaks to the authentication logic. Find the following code block:
And update the audience
property in the verify
method to aud
:
Lastly, the auth token will always encode an email so there is no need to do the following to get the email:
We can get the email from the decodedToken
right away:
This makes the fetchAuth0Email
function useless, so you can remove it.
Deploy the server to Graphcool by running the following:
If it’s your first time using Graphcool, you should be taken to a page to create a Graphcool account.
Your server is set to receive tokens for authentication. You can test this out in the Graphcool playground by running the following command:
We supply the mutation an Auth0 token and we get a node token from Graphcool. Let’s see how we can get tokens from Auth0.
Just like creating an API, you also need to create a client for the project. The client is used to trigger authentication from the browser. On your Auth0 dashboard navigation, click clients and create a new client.
The application type should be set to Single Page Web Applications which is what a routed React app is.
When auth is initiated, it redirects to your Auth0 domain to verify the user. When the user is verified, it needs to redirect the user back to your app. The callback URL is where it comes back to after redirecting. Go to the Settings tab of the client you just created and set the callback URL:
You are now done with setting up a client configuration on the Auth0 dashboard. The next thing we want to do is create a service in our React app that exposes a few methods. These methods will handle utility tasks like triggering authentication, handling response from Auth0, logging out, etc.
First, install the Auth0 JS library:
Then create a services
folder in src
. Add an auth.js
in the new folder with the following content:
Here’s what this code does:
auth0
.handleAuthentication
will be called by one of your components when authentication is completed. Auth0 will pass the token back to you through URL hash. This method reads and passes this hash.storeAuth0Cred
and storeGraphCoolCred
will persist your credentials to localStorage for future use.isAuthenticated
to check if the token stored in localStorage is still valid.getProfile
returns the JSON payload of the user’s profile.You also want to redirect the user to your profile page if they are authenticated, or send them back to the home page (which is the default page) if they are not. The Callback page is the best candidate for this. First, add another route to the routes in App.js
:
/callback
uses the Callback
component which you need to create in src/container/Callback.js
:
This uses the handleAuthentication
method exposed by Auth
to send a mutation to the Graphcool server. You have not yet set up a connection to the server, but once you do and attempt to authenticate a user, this callback page will send a write mutation to the Graphcool server to tell the server that the user exists and is allowed to access resources.
In the Callback component, you used the graphql
(which you have not yet installed) to connect the component to a mutation. This doesn’t imply that there is a connection to the Graphcool server yet. You need to set up this connection using Apollo and then provide the Apollo instance at the top level of your app.
Start with installing the required dependencies:
Update the src/index.js
entry file:
First, this imports all the dependencies. Then this created a link using HttpLink
. The argument passed is an object with the URI. You can get your server’s URI by running the following command on the server folder:
Use the Simple URI to replace the placeholder in the code above.
Next, you created and configured an Apollo client instance with this link as well as a cache. This created client instance is now passed as prop to the Apollo provider which wraps the App
component.
Now that everything is intact, you can add an event to the button on our navigation bar to trigger the auth process:
When the Join button is clicked, we trigger the auth.login
method which would redirect us to our Auth0 domain for authentication.
After the user logs in, Auth0 will ask if the user wants to access their profile information.
After authentication, watch the page move back to /callback
and the /profile
if authentication was successful.
You can also confirm that the user is created by going to the data view in your Graphcool dashboard and opening the Users table.
Next you will want to hide the login
button when the user is authenticated and show the logout button rather. Back in the nav.js
replace the Join
button element with this conditional logic:
The Auth
services exposes a method called isAuthenticated
to check if the token is stored in the localStorage and not expired. Your user will then be logged in.
You can also use the Auth service to retrieve a logged in user profile. This profile is already available in the localStorage:
The nickname will then get printed in the browser.
At this time, an authenticated user will still have access to a restricted backend because you haven’t told the server about the token.
You can send the token as Bearer
token in the header of our request. Update the index.js
with the following:
Instead of creating the Apollo client with just the HTTP Link, you update it to use the middleware you just created which adds a token to all server requests we make:
You can then use the token at the server’s end to validate the request.
In as much as you have done a great job by securing the most important part of your project which is the server and its data, it doesn’t make sense to leave the user hanging at a route where there will be no content. The /profile
route needs to be protected from being accessed when the user is not authenticated.
Update App.js
to redirect to the home page if the user goes to profile but is not authenticated:
You are still using auth.isAuthenticated
to check for authentication. If it returns true, /profile
wins, else, /
wins.
In this tutorial, you authenticated a user using Auth0 in a GraphQL project. What you can do is go to your Auth0 dashboard and add a few more social authentication options like Twitter. You will be asked for your Twitter developer credentials which can get from the Twitter Developer website.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!