DEV Community

loading...
Cover image for Build Login with Google, Github, Facebook on ReactJS [without coding a backend]

Build Login with Google, Github, Facebook on ReactJS [without coding a backend]

kartik0709 profile image Kartik Grewal ・5 min read

One of the most challenging parts I found as a beginner was adding Login flow to my application. As soon as I started on the flow, I kept facing the same bunch of questions over and over again - How to handle passwords, how to handle reset passwords, how should I encrypt and store them, etc. Then came login via 3rd party providers (GitHub, Google, etc.), these made things even easier as now we don't have to worry about storing passwords, resetting them, and all the other headaches that come with passwords.

But it still involved a fair amount of code, and integrating multiple login services is still isn't that straightforward. Then came Canonic!

With Canonic, it became easy to add multiple login providers as you get only one API endpoint that you basically have to use. The process stays the same for all the different logins. In this article, I'll show how you can integrate Google Login with ReactJS, powered by Canonic.

So let's get Started!

Let's start with the backend first. We head over to www.canonic.dev, login and create a new project, we’ll call it “my test app”. We select the “Create” option which basically means that we need a new DB instance for our project (canonic provides one).

We enter the name of our table, let’s name this one “Users”. There are 3 types of tables we can create:

  1. List - This means we’ll be storing multiple records in this table.
  2. Standalone - means we can store only one record in this table.
  3. Identity - creates a user table where we can enable different login providers.

screenshot

We’ll select identity as the type. We’re provided with a bunch of predefined system field that covers most of the user information. You can also add more fields to this table as required.

Now that our table and fields are ready, we need to enable login providers on this table. To open settings, we click on the table, select identity settings from the tabs. You’ll find a list of all the service providers on your left. For our project, we enable Google login.

google-login-enabled

There are 3 fields that we have to fill:

  • Redirect URI → The URL where users will be redirected after logging in to google. (for our app purposes, [http://localhost:3000/](http://localhost:3000) will be our redirect URL)
  • Client ID → Client ID (provided by google)
  • Secret → Secret (provided by google)

Once all the settings are filled, close the panel and hit deploy on the top right corner.

And VOILA! Our APIs are ready for consumption. Now let’s start with the frontend. We’ll use react with GraphQL.

How Frontend will work?

Here's what the flow will look on frontend:

Step 1 - Frontend calls Canonic to get the google URL where the user needs to be redirected to sign-in.

Step 2 - After logging in, google will redirect back to our app with a code.

Step 3 - We send this code back to Canonic to get the authorisation token and user data.

  • We start with CRA (create react app).
npx create-react-app my-test-frontend
cd my-app
npm start
Enter fullscreen mode Exit fullscreen mode

Next, we install GraphQl in our app

yarn add @apollo/client graphql
Enter fullscreen mode Exit fullscreen mode

After GraphQL is installed, we head over to Canonic, to get our GraphQL connection URL. Go to project documentation via the vertical navigation bar, at the bottom left, click on the button named API Playground. You'll see the connection URL in the tab. It'll end in /graphql

graphql-string

Now that we have our connection URL, let's head to the frontend. We open the index.js file and wrap our App in ApolloProvider and create our client.

index.js

import { ApolloClient, InMemoryCache, ApolloProvider } from "@apollo/client";

const client = new ApolloClient({
  uri: "<COPIED-URI-FROM-CANONIC>",
  cache: new InMemoryCache(),
});

ReactDOM.render(
  <React.StrictMode>
    <ApolloProvider client={client}>
      <App />
    </ApolloProvider>
  </React.StrictMode>,
  document.getElementById("root")
);
Enter fullscreen mode Exit fullscreen mode

This will allow our frontend application to connect with our backend.

  • Now we create our Login Component. The screen where login from the google button will be visible. We'll have to fetch our google login redirect URL (the URL we need to redirect users to. when they click on the button).

For that we need to call getLoginUrlsForUser query with the following parameters:

query Login {
  getLoginUrlsForUser {
    GOOGLE
  }
}
Enter fullscreen mode Exit fullscreen mode

We use useQuery to call our API and get the login URL. We create login.js inside the components directory.

import React from "react";
import { useQuery, gql } from "@apollo/client";

const LOGIN_URLS_QUERY = gql`
  query Login {
    getLoginUrlsForUser {
      GOOGLE
    }
  }
`;

function Login() {
  const { loading, error, data } = useQuery(LOGIN_URLS_QUERY);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error :(</p>;


  return <a href={data?.getLoginUrlsForUser?.GOOGLE}>LOGIN with Google</a>;
}

export default Login;
Enter fullscreen mode Exit fullscreen mode

So far we have redirection to google working.

redirection

Next Steps:

to grab the token from the URL when google redirects back to our application —> Send to Canonic, call login API —> Get the authorization token and the user object.

So we add a few lines of code to App.js. Remember, we had filled with [http://localhost:3000/](http://localhost:3000/), so google will redirect back to this URL - with code in the URL (It'll look something like this http://localhost:3000/?code=.......

  • We want to check if there's a code in URL when component mounts (when web app loads) so we use useEffect to check.
useEffect(() => {
    const urlCode = new URLSearchParams(window.location.search).get("code");
    if (urlCode) {
      <CALL-LOGIN-API-HERE>
    }
  }, []);
Enter fullscreen mode Exit fullscreen mode

So we call our login mutation - our mutation would involve two parameters - Code (Google passes it back) and Service (which will be "GOOGLE" in our case).

mutation Login($code: String!, $service: String!) {
  loginForUser(code: $code, service: $service) {
    token
    user {
      _id
      createdAt
      updatedAt
      email
      firstName
      lastName
      avatar {
        url
        name
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

NOTE: Since this is a write operation, we'll need to generate a secret key for our Canonic APIs with appropriate permissions. Go back to Canonic --- Go to your project ---
project settings located in the left vertical menu --- Access Tokens --- Create a new access token. Be sure to select write permission. Read more about it here

  • We combine our mutation and useEffect in App.js will look something like this. We import Login Component in our App and depending on whether we have token or not, we show login component.

App.js

import { useEffect } from "react";
import { gql, useMutation } from "@apollo/client";

import Login from "./components/Login";

import "./App.css";

const LOGIN_MUTATION = gql`
  mutation Login($code: String!, $service: String!) {
    loginForUser(code: $code, service: $service) {
      token
      user {
        _id
        createdAt
        updatedAt
        email
        firstName
        lastName
        avatar {
          url
          name
        }
      }
    }
  }
`;

function App() {
  const [loginMutation, { data }] = useMutation(LOGIN_MUTATION);

  useEffect(() => {
    const urlCode = new URLSearchParams(window.location.search).get("code");
    if (urlCode) {
      loginMutation({ variables: { code: urlCode, service: "GOOGLE" } });
    }
  }, []);

  return (
    <>
      {!data?.loginForUser?.token ? (
        <Login />
      ) : (
                <div>Hi, you're logged in! You're email is {data?.loginForUser?.user?.email}</div>
      )}
    </>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Stitching all this together will get App working something like this:

final-flow

To add more login providers (Github, Facebook), now you simply enable the login provider on Canonic, fill in the required secret, id, and you're good to go!

Feel free to clone this project, add your own project url and give it a spin!

Discussion (0)

Forem Open with the Forem app