In this section, you’ll learn how you can implement authentication functionality with Apollo to provide signup and login features to your users.
As in the sections before, you’ll set the stage for the login functionality by preparing the React components that are needed for this feature. You’ll start by building the Login
component.
Let’s quickly understand the structure of this new component, which can have two major states:
input
fields for the user to provide their email
and password
. Notice that state.login
will be true
in this case.input
field where users can provide their name
. In this case, state.login
will be false
.The method _confirm
will be used to implement the mutations that we need to send for the login functionality.
Next you also need to provide the constants.js
file that we use to define the key for the credentials that we’re storing in the browser’s localStorage
.
Warning: Storing JWTs in
localStorage
is not a safe approach to implement authentication on the frontend. Because this tutorial is focused on GraphQL, we want to keep things simple and therefore are using it here. You can read more about this topic here.
With that component in place, you can go and add a new route to your react-router-dom
setup.
Finally, go ahead and add Link
to the Header
that allows the users to navigate to the Login
page.
You first retrieve the authToken
from local storage. If the authToken
is not available, the submit-button won’t be rendered any more. That way you make sure only authenticated users can create new links.
You’re also adding a second button to the right of the Header
that users can use to login and logout.
Here is what the ready component looks like:
Perfect, you’re all set now to implement the authentication functionality.
signup
and login
are two regular GraphQL mutations you can use in the same way as you did with the createLink
mutation from before.
Both mutations look very similar to the mutations you already saw before. They take a number of arguments and return the token
that you can attach to subsequent requests to authenticate the user (i.e. indicate that a request is made on behalf of that user). You’ll learn 🔜 how to do so.
Before we take a closer look at the <Mutation />
component implementation, go ahead and add the required imports.
Now, let’s understand what’s going with the <Mutation />
component you just added.
The code is pretty straightforward. If the user wants to just login, you’re calling the loginMutation
, otherwise you’re using the signupMutation
, thus mutation will be triggered on the div onClick
event. GraphQL mutations receive email
, password
and name
state values as params passed on variables
prop. Lastly, after the mutation was completed, we call _confirm
function passing as argument the mutation returned data
.
All right, all that’s left to do is implement _confirm
function!
After the mutation was performed, you’re storing the returned token
in localStorage
and navigate back to the root route.
Note: Mutation returned
data
relies on GraphQL mutation definition, that’s why we need to get thetoken
depending on which mutation is triggered.
You can now create an account by providing a name
, email
and password
. Once you did that, the submit-button will be rendered again:
If you haven’t done so before, go ahead and test the login functionality. Run yarn start
and open http://localhost:3000/login
. Then click the need to create an account?-button and provide some user data for the user you’re creating. Finally, click the create account-button. If all went well, the app navigates back to the root route and your user was created. You can verify that the new user is there by sending the users
query in the dev Playground in the database project.
Now that users are able to login and obtain a token that authenticates them against the GraphQL server, you actually need to make sure that the token gets attached to all requests that are sent to the API.
Since all the API requests are actually created and sent by the ApolloClient
instance in your app, you need to make sure it knows about the user’s token! Luckily, Apollo provides a nice way for authenticating all requests by using the concept of middleware, implemented as an Apollo Link.
First, you need to add the required dependencies to the app. Open a terminal, navigate to your project directory and type:
Let’s see the authentication link in action!
This middleware will be invoked every time ApolloClient
sends a request to the server. Apollo Links allow to create middlewares
that let you modify requests before they are sent to the server.
Let’s see how it works in our code, first, we get the authentication token
from local storage
if it exists, after that we return the headers
to the context
so httpLink can read them.
Note: You can read more about Apollo’s authentication here.
That’s it - now all your API requests will be authenticated if a token
is available.
The last thing you’re doing in this chapter is ensure only authenticated users are able to post
new links. Plus, every Link
that’s created by a post
mutation should automatically set the User
who sent the request for its postedBy
field.
To implement this functionality, this time you need to make a small change on the server-side as well.
With this change, you’re extracting the userId
from the Authorization
header of the request and use it to directly connect
it with the Link
that’s created. Note that getUserId
will throw an error if the field is not provided or not valid token could be extracted.
Note: Stop the server and run it again executing
yarn dev
to apply the changes made.