GraphQL Authentication with React Native & Apollo [Part 2/2]

Connecting a React Native app to the Backend

This is the second and final part of a series where I cover how to setup authentication with React Native, GraphQL, and MongoDB. Below is part 1 where we setup the server.

In this part we’ll be building a basic React Native app and connecting it to the backend. We’ll be using Snack to do this so you never have to leave your browser.

Prefer Video?

I made a video version of this tutorial as well, which can be found below:

Setup

We’re focusing on the React Native + Apollo aspect in this tutorial so we won’t be walking through the process of building the UI, below is the Snack with all the components setup.

Note: I had some inconsistency/issues when using native-base on Snack. If you’re having those issues you can run the app locally instead. Here’s a the repo.

https://snack.expo.io/@spencercarli/graphql-authentication-starting

As you can see, there’s not much to it right now. It’s just a bunch of fake verification and UI code.

Connecting to the Backend

Before we move on make sure that you’ve got the URL for your GraphQL endpoint from Launchpad — available in the bottom center of the screen.

Now let’s configure the ApolloClient (note that these instructions are for Apollo v2).

We’ll be using a handful of packages throughout this tutorial. When you import than Snack will automatically install them (if you’re not using Snack then you need to install them from NPM).

To setup the Apollo client we can useapollo-client-preset. At the top of your app.js file add import { ApolloClient, HttpLink, InMemoryCache } from 'apollo-client-preset';

Then create a new ApolloClient instance that points at the GraphQL endpoint.

To make this available to our app we need to use ApolloProvider, pass it the new client, and wrap our app with it.

We should be connected to the backend! Now to interact with it.

Registering Users

If you take a look in Register.js you’ll see that I’ve got some simple logic in place to capture input values, check them, etc. The basics. Now, when a user presses submit, we want to:

  1. Attempt to log them in via the signup mutation
  2. If successful, save the jwt to AsyncStorage
  3. Switch the view the user sees

To accomplish #1 we need to make the Register component aware of the mutation. We’ll use gql to write our graphql query and the graphql higher order component to tap into the Apollo client.

We know that our mutation looks something like this (from working with it directly in Launchpad in part 1).

Now we need to to be able to pass variables from our user to the mutation.

Finally, we want to make this mutation available to the Register component via this.props so that the component agnostic from the Apollo bindings.

Now to use it we’ll go to the end of our handleSubmit function and call it.

That’s only taking care of a piece of the puzzle though. The signup function will return a promise so we can append then and catch to it. When the response is successful we want to save the JWT and we want to show them the profile screen. Both of these will be handled in the changeLoginState that’s being made available on this.props.screenProps.

Also, when an error occurs, we want to highlight the field that caused the error. Note that this is very basic error handling and is not covering all potential errors.

With those considerations in mind that leaves us with

Now let’s improve on that changeLoginState function which is being made available in app.js. It’s already changing to the profile screen for us but we also want to save the JWT.

We’ll be using the signIn and signOut functions from util.js, which are just wrappers around AsyncStorage. Take a moment to understand them.

So if the user is loggedIn save the JWT with the signIn function, otherwise sign them out with signOut.

Great! Now the JWT will be saved and the profile screen will be shown. But as it stands if the app refreshes they’re still shown the sign up screen.

Login with JWT

After signing up they get their JWT and it’s saved to persistent storage (AsyncStorage). We can use this to sign in. All we’ll do is, in app.js, is check if they have a token in AsyncStorage and if so show them the profile.

Note: This is a very trivial implementation. This could be a place where you check if the JWT the user has is still valid and only then show them the profile screen. In the interest of brevity I’ll be skipping that.

getToken is also a small wrapper around AsyncStorage.

This leaves us with the following interaction: when the app is refreshed the user will be automatically logged in.

Sign Out

Since it’s something we need to do to continue on with this tutorial, and our app needs it. We’ll implement signing out.

Actually, if you think back to where we modified handleChangeLoginState we already did everything necessary. When the user is changing their loggedIn state to false we clear the AsyncStorage token that is used to sign in.

So we’re done! Click “Log Out”, refresh the app, and you’ll see it no longer brings you to profile.

Login with Email and Password

Logging in with email and password is just like sign up, we’re just calling a different mutation. I’ll let the code do the talking.

Now to call the login function available on this.props, save the JWT and change screens (on success) or show an error.

Showing User Information

The final thing we’ll do, to demonstrate that things are actually working and it’s not just a big facade, is show the user’s database _id and their email address. We can do that via the currentUser query we set up in Part 1.

This work will happen in the Profile.js file.

The query is very simple, we can just copy exactly what we had in part 1. Put this query inside a graphql higher order component as well.

We pull currentUser off of this.props.data and display the data, if it exists.

If you refresh the app now you’ll see that nothing is changing? Why is that?

Well we’re not passing the JWT along with our request! The server is expecting the JWT to be coming in the authorization header and uses that to find the current user.

To pass this token along with the request we’ll use setContext from the apollo-link-context which is another apollo link we’ll use. First pull the HttpLink we currently have into a variable.

Then, using setContext, we’ll create a new authLink that will fetch our token from storage and append it to the headers.

Finally, we use concat to add the httpLink to our authLink and pass all of that to the ApolloClient. That’s hard to follow, code is easier to understand…

This leaves us with…


I hope you found this series helpful! Let me know if there are other things you’re wanting to see in the realm of React Native + GraphQL.

Final Code:

https://snack.expo.io/HJjWN6_0W

My name is Spencer. I teach people to build 🔥 apps with React Native. Interested in more high quality tutorials? Sign up for my email list.

Additional Exercises

Want to expand on this tutorial? How about…

  1. Checking the validity of a JWT before choosing which layout the user sees
  2. Add some loading indicators to better handle the delay currently shown
  3. Better handle errors
Did you find this helpful? Be sure to 👏 for it!