Use GraphQL to log in (with React and apollo).
Tags: graphql, auth
Published: 2022-02-23 14:27:46

---
title: Use GraphQL to log in (with React and apollo).
published: true
description: 
tags: graphql,auth
series: graphql
cover_image: https://res.cloudinary.com/practicaldev/image/fetch/s--RlqwldxD--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ehd9wcdwrvrn9bu5g4z5.jpg
---

> Hello, feel free to email me PETERLITSZO at GMAIL dot COM if you want to discuss with me!

# RESTful API

In RESTful API, if we want to get the authentication, we can just request by `POST` method, with the JSON data that about username (or email) and password, and then get the session id, or token, or JWT, etc. (See [How to authentication](https://dev.to/peterlitszo/how-to-authentication-2a10) to get more infomations)

# GraphQL

Now we want to do the same thing in GraphQL:

```graphql
query LogIn($email: String!, $password: String!) {
  # Input the email, password, and then output the jwt.
  user(email: $email, password: $password) {
    jwt
  }
}
```

> **UPDATED**: This is question. We know that the RESTful method `GET` will never change the data but only return the data (but you can if you really want).
>
> And GraphQL `query` is same as `GET`. But this time we ask server build a JWT for us, and set the cookie... It looks like not only just return a data.
>
> So if I use `mutation`, will it be a better idea?

We set the string `LOG_IN_QUERY` as the graphql statement above.

To query with graphql after we click the log in button, we need to use hook `useLazyQuery` ([click to get more infomations](https://www.apollographql.com/docs/react/data/queries/#manual-execution-with-uselazyquery)) to get the function to query.

The first part is to import those hooks and function and set const string:

```jsx
import { useState } from 'react';
import { useLazyQuery, gql } from '@apollo/client';

const LOG_IN_QUERY = gql`
  query LogIn($email: String!, $password: String!) {
    # Input email, and password, then output the jwt.
    user(email: $email, password: $password) {
      jwt
    }
  }
`;
```

Then we need a component to handle the login:

```jsx
// React function component, export to be used in other
// JavaScript files.
export default () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const [login, { loading, error, data }]
    = useLazyQuery(LOG_IN_QUERY);

  // If we call login, the boolean value, that loading,
  // error, and data turn into, will be false.
  //
  // So there is other logic to deal with error, loading,
  // and data.

  return (
    <div>
      {/* Input box to input email */}
      <input
        value={email}
        onChange={(event) => setEmail(event.target.value)}
      />
      {/* Input box to input password */}
      <input
        value={password}
        onChange={(event) => setPassword(event.target.value)}
      />
      {/* Button to log in */}
      <button
        onClick={
          () => login({ variables: { email, password } })
        }
      >
        Log in
      </button>
    </div>
  );
}
```

Well, that is all.

# GraphQL with `HttpOnly` cookie

Let the JavaScript can touch the cookie is danger. We can let the server give us a response with `Set-Cookie` with `HttpOnly` flag! It will be safe to avoid JavaScript to deal with cookie!

Now we need change the GraphQL statement, and let the server return response with `Set-Cookie: jwt=<THE JWT SERVER RETURN>; HttpOnly`:

```graphql
query LogIn($email: String!, $password: String!) {
  # Input the email, password, and then output the jwt.
  user(email: $email, password: $password) {
    # Do you have a better idea than use underscore?
    # If I remove all content, it will raise an error.
    _
  }
}
```

We use cookie to get the authentication, so we will use `js-cookie` to get if we already have the `jwt` cookie or not.

```JavaScript
import Cookie from 'js-cookie';
import { useEffect } from 'react';
import { useNavigate } from 'react-router';
```

If we already signed in, we will return the previous page:

```JavaScript
// ...

const navigator = useNavigate();

useEffect(() => {
  if (Cookie.get('jwt')) {
    navigator(-1); // go back
  }
});

// ...
```

See here to get more information: [Deal with `HttpOnly` cookies](https://dev.to/peterlitszo/deal-with-httponly-cookies-1i5a).

# Others

Here is some link to get more information, Please read those! Those are really awesome!!!:

* [Apollo link context](https://www.apollographql.com/docs/react/api/link/apollo-link-context/), a way to set HTTP header to set the authorization.

* [Apollo authorization](https://www.apollographql.com/docs/react/networking/authentication/). The way to get authorization with apollo.

* [How to authenticate using GraphQL Cookies and JWT](https://flaviocopes.com/graphql-auth-apollo-jwt-cookies/)(Key words: A runable JavaScript GraphQL server, A client that store JWT in cookie. By the way, remember some package **HAS BEEN DEPRECATED**, for example, `apollo-link-context`, `@apollo/link-context` and so on. Be sure read the README.md of those projects).