Hi! We know that authentication flow is a crucial feature in most websites. If we want our users to only access the features of an application, we need to make sure that this user is authenticated. But implementing an authentication flow can take more effort than it needs to. Therefore, we have OAuth flows, basically we delegate the auth process to an external provider: Facebook, LinkedIn, Google, or, in this case, GitHub.

image.png

This is an example how the OAuth flow works

Ok, so let’s imagine that you have a component on ReactJS that has a button to log in with GitHub, just like the image bellow:

image.png

"use client";

import React from "react";
import { IoLogoGithub } from "react-icons/io";

export function GitHubButtonComponent() {
  return (
      <button
        className="rounded-xl gap-2 bg-darkOrange flex items-center justify-center p-4 w-64"
        type="button">
          <p className="font-semibold text-white">Github</p>
          <IoLogoGithub size={24} fill="white" />
      </button>
  );
}

With that in hand, following the flow diagram from the first image in this article, we need to make sure that the client (the app itself) is able to be redirected to the authorization provider URL (GitHub). First let’s create an async function to perform this redirect, and use some hooks to help us navigation:

"use client";

import React from "react";
import axios from "axios"; // Using axios to make HTTP requests
import { useEffect, useCallback, useState } from "react"; // Using React hooks to deal with side effects, state, and performance
import { useSearchParams, useRouter } from "next/navigation"; // Using Nextjs hook to implement navigation behaviour
import { IoLogoGithub } from "react-icons/io";

export function GitHubButtonComponent() {
  const [isAuthenticating, setIsAuthenticating] = useState<boolean>(false);
  const [errorOnRequest, setErrorOnRequest] = useState<boolean>(false);
  const params = useSearchParams();
  const router = useRouter();
  
  return (
      <button
        className="rounded-xl gap-2 bg-darkOrange flex items-center justify-center p-4 w-64"
        type="button"
        onClick={async () => { // Adding event to redirect to GitHub
          router.push(
            `https://github.com/login/oauth/authorize?client_id=${process.env.NEXT_PUBLIC_CLIENT_ID}`
          );
        }}
        >
          <p className="font-semibold text-white">Github</p>
          <IoLogoGithub size={24} fill="white" />
      </button>
  );
}

Disclaimer: In this article Nextjs is being used to deal with routing and navigation, using the useRouter hook from “next/navigation

Above we use router to redirect the user to the GitHub authorization server when the user clicks the button. Also, the useState isAuthenticating was added to create a visual loading state feedback for the user, it should look like this:

oauth-video-loading - Made with Clipchamp.mp4

Note that, after you get redirected back to your application, in the URL you’ll see that you have a code?${GITHUB_CODE}, we will use that to complete our authentication flow.

Ok, so the first part of our OAuth flow is done. Is time to make the exchange of this provided code into an access token that we can use to deal with authentication logic (e.g. make sure that the user is authenticated, or to make requests to GitHub API). So, ideally you would have a backend service, let’s say an Express application. And inside your index.ts, you created an endpoint to perform a token exchange and return an access token to your client. Like this: