DEV Community

Cover image for Use GraphQL to log in (with React and apollo).
peterlits zo
peterlits zo

Posted on • Updated on

Use GraphQL to log in (with React and apollo).

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 to get more infomations)

GraphQL

Now we want to do the same thing in GraphQL:

query LogIn($email: String!, $password: String!) {
  # Input the email, password, and then output the jwt.
  user(email: $email, password: $password) {
    jwt
  }
}
Enter fullscreen mode Exit fullscreen mode

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) to get the function to query.

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

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
    }
  }
`;
Enter fullscreen mode Exit fullscreen mode

Then we need a component to handle the login:

// 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>
  );
}
Enter fullscreen mode Exit fullscreen mode

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:

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.
    _
  }
}
Enter fullscreen mode Exit fullscreen mode

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

import Cookie from 'js-cookie';
import { useEffect } from 'react';
import { useNavigate } from 'react-router';
Enter fullscreen mode Exit fullscreen mode

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

// ...

const navigator = useNavigate();

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

// ...
Enter fullscreen mode Exit fullscreen mode

See here to get more information: Deal with HttpOnly cookies.

Others

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

Top comments (0)