Authenticate your React App with Appwrite

Arindam Majumder - Dec 23 '23 - - Dev Community

## Introduction

User authentication is a crucial aspect of modern web applications. Implementing user authentication from scratch is not an easy task. However, With Appwrite we can easily perform user Authentication.

In this article, We'll explore How to implement User Authentication using Appwrite in our React App.

So, Without delaying further, Let's Start!

What is Appwrite?

Appwrite Logo

Before Jumping on the Auth Implementation let's understand what is Appwrite!

Appwrite is an open-source, self-hosted BaaS that provides a set of APIs to handle common backend needs like user authentication, file storage, databases, etc.

It aims to help developers build applications faster and more securely by abstracting away these backend tasks.

Project Setup:

For this article, I'm using a starter template from Dennis Ivy. But, you can apply the same techniques to your own project.

Here's the link to the starter template.

After cloning this code, Just run npm install and That's it!

You can check if it's working or not by Running the following command

npm run dev
Enter fullscreen mode Exit fullscreen mode

It will show something like this!

Sample App UI

Appwrite Console Setup:

Firstly, we'll set up and configure the Appwrite console for our project!

At first, Go to the Appwrite Console.

After Creating your account, Create a New Project.

Appwrite dashboard

Here I'm creating One Project named "React-Auth". Now You have to choose Web as we'll be working on a Web App.

Add a platform

After That, We'll Add the name of our Web app and the hostname!

Now, We'll install the Appwrite SDK using the following command:

npm install appwrite
Enter fullscreen mode Exit fullscreen mode

So, We have installed Appwrite SDK. Next, We'll Add Appwrite to our project. For that, We'll create a appwriteConfig.js file in the src directory.

//src/appwriteConfig.js

import { Client, Account } from 'appwrite';

export const API_ENDPOINT = 'https://cloud.appwrite.io/v1'
export const PROJECT_ID = 'YOUR PROJECT ID' //Replace this with your project ID

const client = new Client()
    .setEndpoint(API_ENDPOINT) 
    .setProject(PROJECT_ID);    

export const account = new Account(client);

export default client;
Enter fullscreen mode Exit fullscreen mode

Lastly, We'll manually create a user from the Appwrite console. After Creating the user, Your console should look like this:

Appwrite Console

Okay! So We have set up & configured the Appwrite Console. Now let's move to the Main Section!

Authentication:

Appwrite Authentication

In this section, we'll do the authentication!

For that, we'll create a AuthContext.jsx file to manage the Auth state and different functions.

Here's the code for that:

//utils/AuthContext.jsx
import { createContext, useState, useEffect, useContext } from "react";

const AuthContext = createContext()

export const AuthProvider = ({children}) => {

        const [loading, setLoading] = useState(true)
        const [user, setUser] = useState(null)

        useEffect(() => {
            setLoading(false)
         }, [])

         const loginUser = async (userInfo) => {}

         const logoutUser = async () => {}

         const registerUser = async (userInfo) => {}

         const checkUserStatus = async () => {}

        const contextData = {
            user,
            loginUser,
            logoutUser,
            registerUser
        }

    return(
        <AuthContext.Provider value={contextData}>
            {loading ? <p>Loading...</p> : children}
        </AuthContext.Provider>
    )
}

//Custom Hook
export const useAuth = ()=> {return useContext(AuthContext)}

export default AuthContext;
Enter fullscreen mode Exit fullscreen mode

Here we have created AuthContext to manage the user auth state and some Functions for user authentication. Currently, these functions are empty! We'll add those in the later steps!

The AuthProvider component wraps the entire application with the authentication context

We have also created a custom hook useAuth to access this context.

Next, We will wrap the routes in App.jsx with AuthProvider.

The Code will look like this:

...
import { AuthProvider } from './utils/AuthContext'

function App() {
    return (
        <Router>
            <AuthProvider>
                <Header/>
                <Routes>
                    ...
                </Routes>
            </AuthProvider>
        </Router>
    );
}
Enter fullscreen mode Exit fullscreen mode

User Sign Up:

Till now, We have created the Auth functions and done the basic setup! Now we'll register/sign up our user.

For that, At first, we'll Import registerUser from AuthContext.jsx that we have created before.

//pages/Register.jsx
import { useAuth } from '../utils/AuthContext'
..
const {registerUser} = useAuth()
Enter fullscreen mode Exit fullscreen mode

Next, We'll handle the form submission with Submithandler and ref.

Here's the code for that:

import React, { useEffect, useRef } from 'react'
...
const registerForm = useRef(null)

const handleSubmit = (e) => {
    e.preventDefault()
    // Taking the values from the form
    const name = registerForm.current.name.value
    const email = registerForm.current.email.value
    const password1 = registerForm.current.password1.value
    const password2 = registerForm.current.password2.value
    //Password validation
    if(password1 !== password2){
        alert('Passwords did not match!')
        return 
    }

    const userInfo = {name, email, password1, password2}

    registerUser(userInfo)
}

...

<form ref={registerForm} onSubmit={handleSubmit}>
Enter fullscreen mode Exit fullscreen mode

Here we have also added one check for the password confirmation, which will throw an alert if the passwords are not the same!

After that, we have taken all the values in an object (userInfo) and passed that to registerUser function that we have imported from AuthContext.jsx.

Finally, We will handle the Registration in the AuthContext.jsx where we have already created an empty registerUser function. Now we'll add functionalities to that!

💡
Note: To create a Unique ID for each user we'll use the {ID} provided by appwrite. ID.unique() will create a unique ID!

So Now we'll add this to AuthContext.jsx :

//AuthContext.jsx
import { useNavigate } from "react-router-dom";
import { ID} from 'appwrite';

...
const navigate = useNavigate()

const registerUser = async (userInfo) => {
    setLoading(true)
    try{
        let response = await account.create(ID.unique(), userInfo.email, userInfo.password1, userInfo.name);
        await account.createEmailSession(userInfo.email, userInfo.password1)
        let accountDetails = await account.get();
        setUser(accountDetails)
        navigate('/')
    }catch(error){
        console.error(error)
    }
    setLoading(false)
}
Enter fullscreen mode Exit fullscreen mode

Cool! Now we have done the registration part! Now we can register new users.

User Login:

Now, We'll work on the Login part! It's quite straightforward!

Firstly, we'll Import the User login Function from AuthContext.

//pages/login.jsx
import { useAuth } from '../utils/AuthContext'
...

const {user, loginUser} = useAuth()
Enter fullscreen mode Exit fullscreen mode

Next, Just like Signup, We'll handle the form submission with Submithandler and ref.

//Import useRef
import React, { useEffect, useRef } from 'react'

//Add loginForm ref
const loginForm = useRef(null)

//Form submit handler
  const handleSubmit = (e) => {
    e.preventDefault()
    const email = loginForm.current.email.value
    const password = loginForm.current.password.value

    const userInfo = {email, password}

    loginUser(userInfo)
  }

//Add ref and submit function to form
<form onSubmit={handleSubmit} ref={loginForm}>
Enter fullscreen mode Exit fullscreen mode

After that, we'll Import account from appwriteConfig and add functionality to the loginUser method.

//utils/AuthContext.jsx
...
import { account } from "../appwriteConfig";
...
const loginUser = async (userInfo) => {
    setLoading(true)
    try{
        let response = await account.createEmailSession(userInfo.email, userInfo.password)
        let accountDetails = await account.get();
        setUser(accountDetails)
    }catch(error){
        console.error(error)
    }
    setLoading(false)
}
Enter fullscreen mode Exit fullscreen mode

As simple as that! We have done the Login part! Now we can LogIn our user!

Checking User Status:

We can check the user status by calling the checkUserStatus method. It will now update the user and loading state from the useEffect hook.

//utils/AuthContext.jsx
useEffect(() => {
    //setLoading(false)
    checkUserStatus()
}, [])
const checkUserStatus = async () => {
    try{
        let accountDetails = await account.get();
        setUser(accountDetails)
    }catch(error){  
    }
    setLoading(false)
}
Enter fullscreen mode Exit fullscreen mode

User LogOut:

So, We have done SignUp and LogIn methods! Now we'll add the final part of our Authentication which is Logout!

It's very easy!

//components/Header.jsx
const {user, logoutUser} = useAuth()

//trigger the logoutUser method
<button onClick={logoutUser} className="btn">Logout</button>
Enter fullscreen mode Exit fullscreen mode

For logging out the user we will use account.deleteSession method. It will delete the current session of the user.

//utils/AuthContext.jsx
const logoutUser = async () => {
    await account.deleteSession('current');
    setUser(null)
}
Enter fullscreen mode Exit fullscreen mode

And That's it! We have Completed our Authentication part!

Now, you can follow the same steps to authenticate your React app with Appwrite.

Easy peasy!

Conclusion

If you found this blog post helpful, please consider sharing it with others who might benefit. You can also follow me for more content on Javascript and other web development topics.

To sponsor my work, please visit: Arindam's Sponsor Page and explore the various sponsorship options.

Connect with me on Twitter, LinkedIn, Youtube and GitHub.

Thank you for Reading :)

Thank You Image

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .