Integrating Arcana Auth SDK to a React application

Integrating Arcana Auth SDK to a React application

Etisha Garg
Etisha Garg

In this tutorial, we integrate Arcana Auth SDK to a dApp which will let users login and authenticate into Web3 applications seamlessly, with the familiarity and simplicity of Web2 login experience, while ensuring secure access. Through this blog, we demonstrate the ease with which you can onboard dApp users through social and passwordless auth mechanisms supported by Arcana Auth SDK.

File Structure

Prerequisites

Before getting started with using Arcana Auth SDK in your dApp, you first need to use Arcana Network Dashboard and configure the dApp settings. After completing dApp configuration, we will have to install the dependencies and start building the web application.

Step-1: Register the dApp via Arcana Developer Dashboard

For registering your dApp on Arcana Developer Dashboard, you simply need to go to https://dashboard.beta.arcana.network/ and register by logging in and filling in some details such as App Name and the region where you want to store the data. For more details, check out configure dApp.

Step-2: Configure the dApp settings

After registering the dApp, the next step is to specify the configuration details which will allow dApp users to sign in using passwordless and various social authentication mechanisms such as Google, Discord, Twitch, Github and Twitter.

Next, click on the Auth tab in Arcana Dashboard and specify the details such as Client ID and Client Secret in the Social Auth section.

If you are not sure from where you can get these details to fill in to your dashboard for each social auth, simply follow the steps mentioned for each mechanism here within Authenticate, How To Guide.

Step-3: Enable Wallet UI Mode

In the Arcana Dashboard Auth tab, after the Social Auth section ClientID setup, we need to scroll down to the Wallet section and Enable the Wallet UI mode toggle. To read more about Wallet UI modes, check out Arcana Wallet and UI Modes.

Step-4: Get Arcana App ID

Click Save to save the dApp configuration.

After saving the dApp configuration on the Arcana Dashboard, the dApp is assigned a unique appID. This is used during Arcana SDK initialisation later.

Getting Started

It's time to start working on our React application. Let's start building the app by creating a new React project.

npx create-react-app arcana-auth-integration-react

Now, we will navigate to the newly made folder and start up a development server.

cd arcana-auth-integration-react
npm start

Open up http://localhost:3000, and you should see something that looks like this:

Next, we will install Arcana Auth SDK.

npm install @arcana/auth

Creating useArcanaAuth.js

Now to start writing some code, first we'll create a new file within the src folder and name it useArcanaAuth.js which will have the desired code to import and initialise the Auth SDK. We will also create functions calling different Auth APIs to login via social and passwordless authentication, checking if user is logged in or logged out, for instance.

Let's create that file and add the following code.

import { AppMode, AuthProvider } from "@arcana/auth";
import { useEffect, useState } from "react";

//Config
const appId = 20;

let auth;

function useArcanaAuth() {
  const [initialized, setInitialized] = useState(false);

  const initializeAuth = async () => {
    if (!auth) {
      auth = new AuthProvider(appId);
      await auth.init({ appMode: AppMode.NoUI, position: "right" });
      setInitialized(true);
    }
  }

  //Check isLoggedIn
  const isLoggedIn = async () => {
    if(initialized) {
      return await auth.isLoggedIn();
    }
  }

  //Social Login
  
  const login = async (socialType) => {
    if(initialized) {
      await auth.loginWithSocial(socialType);
    }
  }

  //Email link/Passwordless login
  const loginWithLink = async (email) => {
    if(initialized) {
      await auth.loginWithLink(email);
    }
  }

  //Getting user Accounts
  const getAccounts = async () => {
    if(initialized) {
      return await auth.provider.request({ method: "eth_accounts" });
    }
  }
  
  //Logout
  const logout = async () => {
    if(initialized) {
      return await auth.logout();
    }
  }

  return {
    initializeAuth,
    isLoggedIn,
    login,
    loginWithLink,
    getAccounts,
    logout,
    initialized,
  };
}

export default useArcanaAuth;

Let's try to understand the above code. We first imported the AuthProvider and AppMode from Arcana Auth SDK.

import { AppMode, AuthProvider } from '@arcana/auth'

Then, we specified the appID assigned to our dApp in the Arcana Developer dashboard. In the example below, appID is '20':

const appId = 20

After that, we create and initialize AuthProvider. The dApp must wait until the initialisation is complete before invoking any of the other Auth SDK functions.

auth = new AuthProvider(appId)
await auth.init({ appMode: AppMode.NoUI, ‘right’})

Once the AuthProvider is imported and initialized, we call different Auth APIs within different functions which we'll use later in the App.js file.

Creating the front-end

It's time to build the login page and import the file we have created above so that we can call the functions defined above. The code written in App.js becomes the front-end in our React App. So, remove the existing code that is present and copy the code given below.

import React, { useState, useEffect } from 'react';
import { ColorRing } from 'react-loader-spinner';
import './App.css';

import useArcanaAuth from './useArcanaAuth';

function App() {
  const [loading, setLoading] = useState(true);
  const [loggedIn, setLoggedIn] = useState(false);
  const [email, setEmail] = useState('');
  const [account, setAccount] = useState('');

  const {
    initializeAuth,
    isLoggedIn,
    getAccounts,
    login,
    loginWithLink,
    logout,
    initialized,
  } = useArcanaAuth();

  const initialize = async () => {
    await initializeAuth();
  };

  const handleLogout = async () => {
    setLoggedIn(false);
    await logout();
  };

  useEffect(() => {
    initialize();
  }, []);

  useEffect(() => {
    const loadDetails = async () => {
      if (initialized) {
        const isLogged = await isLoggedIn();
        if (isLogged) {
          setLoggedIn(true);
          const acc = await getAccounts();
          setAccount(acc[0]);
          setLoading(false);
        } else {
          setLoading(false);
        }
      }
    };
    loadDetails();
  }, [initialized]);

  const handleEmailChange = (event) => {
    setEmail(event.target.value);
  };

  return (
    <div className='container'>
      <h1>AUTHENTICATION</h1>
      <div>
        {loading ? (
          <div className='loading'>
            <ColorRing
              visible={true}
              height='100'
              width='80'
              ariaLabel='blocks-loading'
              wrapperStyle={{}}
              wrapperClass='blocks-wrapper'
              colors={['#000000']}
            />
          </div>
        ) : !loading && loggedIn ? (
          <div>
            <h2 className='sub-heading'>Logged In</h2>
            <h3>Welcome {account}</h3>
            <h3>you're logged in successfully.</h3>
            <button className='big-button' onClick={handleLogout}>
              Logout
            </button>
          </div>
        ) : (
          <div className='box'>
            <h2 className='sub-heading'>Select a login</h2>
            <div className='options'>
              <button className='big-button' onClick={() => login('google')}>
                Google Login
              </button>
              <button className='big-button' onClick={() => login('twitch')}>
                Twitch Login
              </button>
              <button className='big-button' onClick={() => login('discord')}>
                Discord Login
              </button>
              <button className='big-button' onClick={() => login('twitter')}>
                Twitter Login
              </button>
            </div>
            <div className='form'>
              <input
                value={email}
                type='text'
                placeholder='Enter email'
                onChange={handleEmailChange}
              />
              <button
                className='big-button'
                onClick={() => loginWithLink(email)}
              >
                Login with link
              </button>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

export default App;

The above code simply creates three views basing the condition on the variables loading and loggedIn.

  • If the loading variable is true, it show the loading spinner.
  • If loading variable is false and the user is not logged in, it shows multiple options to login in.
  • And, if loading variable is false and the user is logged in, it shows the user's address with a welcome message and a logout button which takes the user back to the login page, and sets the loggedIn variable to be false.  

Before running the application, we will also have to install react-spinner-loader which provides a simple React SVG spinner component which will be shown on the screen before data loads to the view.

npm install react-loader-spinner --save

Let's navigate to http://localhost:3000 again, and you should see a web page wherein users have the option to login via social authentication mechanisms or by simply providing their email address which sends a login email to their email ID.

Once the user is logged in, it shows the user their public address with a welcome message and gives a button to logout which when clicked takes the user back to the authentication page.

And, we are done. Using Arcana Auth to our dApp is pretty simple, right?

But wait. Do you also feel like this app is looking a bit rough? So, why not use some CSS?

Copy the below code and paste to the App.css file and you should be good to go.

@import url("https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&family=Sora:wght@400;600&display=block");
* {
  font-family: "Sora", sans-serif;
  margin: 0;
}

h1 {
  text-align: center;
  margin: 10px 0;
}

h1,h2,h3 {
  font-family: "Montserrat", sans-serif;
}

h3 {
  margin-top: 7px;
  margin-bottom: 7px;
}

main {
  border: 1px solid black;
  padding: 5px 5px;
}

.container {
  width: 50%;
  text-align: center;
  margin: 0 auto;
}

.loading {
  text-align: center;
}

.big-button {
  display: block;
  margin: auto;
  width: 300px;
  padding: 0.75em 1.5em;
  font-size: 0.9rem;
  background-color: white;
  border-color: black;
}

.big-button:hover {
  background-color:black;
  color: white;
}

.options {
    display: flex;
    flex-direction: column;
    justify-content: center;
    width: 100%;
    column-gap: 2in;
}

.form {
  display: grid;
  grid-template-columns: 1fr auto;
}


.sub-heading {
  text-align: center;
  color: white;
  background-color: black;
  padding: 15px 15px;
  margin-bottom: 7px;
}

.box {
  border: 1px solid black;
}

Here's a working demo of how the final project would look like:

0:00
/

Full Code repository

Wohoo! Congratulations!🥳

We’ve finally created a dApp which lets users login via social and passwordless login. All you had to do was integrate the Arcana Auth SDK. If you want to take a look at the full source code, find the repo below.

What's Next?

It's time for you to play around with the code and build some kickass dApps using Arcana. You can also try out the AppMode and make use of Arcana Storage SDK as well to add more functionalities to your application.

About Arcana Network

Built for Ethereum and EVM-based chains, Arcana is the web3 infrastructure to easily onboard dApp users and enable user data privacy and ownership. Web3 developers use Arcana’s SDKs for a seamless, familiar user onboarding experience via social authentication and passwordless login. All user data is encrypted, secured with data access fully controlled by the users, and powered by blockchain.

Arcana has raised 2.7Mn USD from some of the leading investors and founders in the ecosystem such as Balaji Srinivasan, Founders of Polygon, Woodstock, Republic Crypto, and Digital Currency Group.

Want to know more about our latest testnet features? Book a demo.

Official Links: Website | Twitter | Discord| Telegram | TG Announcement | Medium | GitHub