Manage User Authentication in Next.js 13
Published: 2023-01-04 08:03:59

Authentication is one of the most critical aspects of building web applications. It helps protect your users’ data and provides an extra layer of security by preventing unauthorized access. Next.js 13 handles authentication in the simplest yet most effective way with advanced routing for progressive web applications.

This article will highlight the new Next.js features on authentication and how you can use [Appwrite](https://appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog) to implement user authentication. The project repository can be found [here](https://github.com/Mr-Malomz/next-appwrite-auth).

## Prerequisites

-   [Node.js](https://nodejs.org/) installed - It comes with Node Package Module(`NPM`) that is used to install and manage packages for Next.js and Appwrite web SDK
-   [Docker](https://docs.docker.com/engine/install/) installed - Docker is used to install Appwrite locally
-   Basic knowledge of React

Next.js version 13 brings enhanced features and performance, including new features for implementing authentication and creating protected routes by introducing middleware to enable full flexibility with the Next.js router.

This article will demonstrate how to use Appwrite to authenticate users in a Next.js application.

## Authentication using Appwrite

[Appwrite](https://appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog) is an open-source project that provides an end-to-end solution for managing the entire lifecycle of your app, from development to deployment. It is designed to make it easy to develop, test, and deploy your app with minimal configuration.

## Installing Appwrite

First, ensure that Docker is properly installed in your development environment. You can confirm the installation by running the following command on your terminal:

```bash
docker
```

![](https://paper-attachments.dropboxusercontent.com/s_7F69E8B1D13F2420C6EC6F0EB80DB64ECEF136BC45C188C940948A7F6BFC4C13_1669591275002_image.png)

To install Appwrite, use the following commands based on your operating system:

Windows Command Prompt(CMD):

```bash
docker run -it --rm ^
    --volume //var/run/docker.sock:/var/run/docker.sock ^
    --volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^
    --entrypoint="install" ^
    appwrite/appwrite:1.1.1
```

Unix:

```bash
docker run -it --rm \
    --volume /var/run/docker.sock:/var/run/docker.sock \
    --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \
    --entrypoint="install" \
    appwrite/appwrite:1.1.1
```

Once the installation is complete, open a web browser and load the Appwrite server URL from the installation configurations:

![](https://paper-attachments.dropboxusercontent.com/s_7F69E8B1D13F2420C6EC6F0EB80DB64ECEF136BC45C188C940948A7F6BFC4C13_1669592479480_Screenshot+from+2022-11-27+21-05-18.png)

```bash
localhost:<port_number>
```

On loading the Appwrite on your browser, you will be redirected to a login page:

![](https://paper-attachments.dropboxusercontent.com/s_6EF4A6F48923F724F3C7B1650D1E95351534F1C48D7BEB524F67CA4F7DD6141E_1692017543443_Screenshot+2023-08-14+at+13.46.18.png)

Create a new user account by clicking on the Sign Up link. After successful registration, you will be redirected to a new page to create a new project:

![](https://paper-attachments.dropboxusercontent.com/s_6EF4A6F48923F724F3C7B1650D1E95351534F1C48D7BEB524F67CA4F7DD6141E_1692017554849_Screenshot+2023-08-14+at+13.46.50.png)

Enter the name of the project and proceed to create a project:

![](https://paper-attachments.dropboxusercontent.com/s_6EF4A6F48923F724F3C7B1650D1E95351534F1C48D7BEB524F67CA4F7DD6141E_1692017571066_Screenshot+2023-08-14+at+13.48.20.png)

## Set up a Next.js project

To set up a project using the latest version of Next.js, 13, run the following command on your command line tool:

```bash
npx create-next-app@latest
```

or

```bash
yarn create next-app
```

The new version asks for a few questions; you can answer them as shown below:

```bash
Would you like to use TypeScript? <No>
Would you like to use ESLint? <No>
Would you like to use Tailwind CSS? <Yes>
Would you like to use `src/` directory? <Yes>
Would you like to use App Router? (recommended) <Yes>
Would you like to customize the default import alias? <Yes>
What import alias would you like configured? @/* <Press Enter>
```

## Connecting to Appwrite

To connect a Next.js application with Appwrite, install the `appwrite` module using:

```bash
npm install appwrite
```

Create a new directory called `utils`, and inside add a new appwrite configuration file: `appwriteClient.js`

Create a library file to establish the connection and use the code snippet below:

```js
import { Client, Account, ID } from 'appwrite';

//create client
const client = new Client();
client
	.setEndpoint('http://localhost/v1')
	.setProject('YOUR PROJECTID GIES HERE');

//create account
const account = new Account(client);

export const createAccount = (email, password, name) =>
	account.create(ID.unique(), email, password, name);

export const createUserSession = (email, password) =>
	account.createEmailSession(email, password);

export const getAccount = () => account.get();

export const logout = () => account.deleteSession('current');
```

Code Explanation:

```js
export const createAccount = async (email, password, name) =>
	account.create(ID.unique(), email, password, name);
```

The `createAccount` function takes an `email`, `password`, and `name` parameters. The function calls the `create` method on the `account` instance to register a new user by passing a unique ID generated using `ID.unique()` and the provided `email`, `password`, and `name` values.

```js
export const createUserSession = async (email, password) =>
	account.createEmailSession(email, password);
```

The `createUserSession` function takes an `email` and `password` parameter. The function calls the `createEmailSession` method to log in users using the `account` instance and passing the provided `email` and `password`.

```js
export const getAccount = () => account.get();

export const logout = () => account.deleteSession('current');
```

The `getAccount` and `logout` function gets details of logged-in users and log-out users, respectively.

## Building the application UI

The application will consist of three pages; a sign-in, sign-up, and an authenticated page.

**Sign-in page**

To do this, first, you will create a `signin/page.js` file inside the `app` folder and add the snippet below:

```js
'use client';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { createUserSession } from '../../../utils/appwriteClient';
import Link from 'next/link';

export default function SignIn() {
    const router = useRouter();
    const [value, setValue] = useState({ email: '', password: '' });
    const [isLoading, setIsLoading] = useState(false);

    const handleChange = (e) => {
        setValue({ ...value, [e.target.name]: e.target.value });
    };

    const handleSubmit = (e) => {
        e.preventDefault();
        setIsLoading(true);
        const { email, password } = value;
        createUserSession(email, password)
            .then((res) => {
                setIsLoading(false);
                router.push('/');
            })
            .catch((e) => {
                setIsLoading(false);
                alert('Incorrect email or password!!!');
            });
    };
    return (
        //UI code goes here
    );
}
```

The snippet above imports the required dependencies, manage the application state, and creates an `handleSubmit` function that uses the `createUserSession` to authenticate users.

Lastly, you will update the application UI using the states and function created above.

```js
//import goes here

export default function SignIn() {
    //states and function goes here

    return (
        <div className='w-screen h-screen bg-white'>
            <main className='py-4 px-4 lg:py-10 lg:px-10 w-full'>
                <div className='flex justify-center mb-8'>
                    <h1 className='text-2xl font-medium text-gray-700'>
                        Authentication with Appwrite and Nextjs 13
                    </h1>
                </div>
                <section className='flex justify-center'>
                    <div className='px-4 py-2 border rounded-lg w-full lg:w-2/4'>
                        <div className='border-b h-8 mb-4'>
                            <h3 className='text-gray-700'>
                                Sign in with your details
                            </h3>
                        </div>
                        <form onSubmit={handleSubmit}>
                            <fieldset>
                                <label className='text-sm text-gray-400 mb-4 block'>
                                    Email
                                </label>
                                <input
                                    name='email'
                                    className='border w-full rounded-sm mb-6 p-2'
                                    required
                                    value={value.email}
                                    onChange={handleChange}
                                    type='email'
                                />
                            </fieldset>
                            <fieldset>
                                <label className='text-sm text-gray-400 mb-4 block'>
                                    Password
                                </label>
                                <input
                                    name='password'
                                    className='border w-full rounded-sm mb-6 p-2'
                                    required
                                    value={value.password}
                                    onChange={handleChange}
                                    type='password'
                                />
                            </fieldset>
                            <button
                                className='text-sm text-white px-8 py-2 rounded-sm bg-blue-600 hover:bg-blue-700'
                                disabled={isLoading}
                            >
                                Sign in
                            </button>
                            <div className='flex mt-6'>
                                <p>Don't have an account?</p>{' '}
                                <Link
                                    href='/signup'
                                    className='ml-2 text-blue-600 font-medium'
                                >
                                    Sign up
                                </Link>
                            </div>
                        </form>
                    </div>
                </section>
            </main>
        </div>
    );
}
```

**Sign-up page**

In the same `app` folder, you will first create a `signup/page.js` file and add the snippet below:

```js
'use client';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { createAccount } from '../../../utils/appwriteClient';
import Link from 'next/link';

export default function SignUp() {
    const router = useRouter();
    const [value, setValue] = useState({ name: '', email: '', password: '' });
    const [isLoading, setIsLoading] = useState(false);

    const handleChange = (e) => {
        setValue({ ...value, [e.target.name]: e.target.value });
    };

    const handleSubmit = (e) => {
        e.preventDefault();
        setIsLoading(true);
        const { email, name, password } = value;
        createAccount(email, password, name)
            .then((res) => {
                setIsLoading(false);
                alert('Account created successfully! you can now login');
                router.push('/signin');
            })
            .catch((e) => {
                setIsLoading(false);
                alert('Error creating user');
            });
    };
    return (
        //UI code goes here
    );
}
```

The snippet above imports the required dependencies, manage the application state, and creates an `handleSubmit` function that uses the `createAccount` to sign-up new users.

Lastly, you will update the application UI using the states and function created above.

```js
//import goes here

export default function SignUp() {
    //states and function goes here

    return (
        <div className='w-screen h-screen bg-white'>
            <main className='py-4 px-4 lg:py-10 lg:px-10 w-full'>
                <div className='flex justify-center mb-8'>
                    <h1 className='text-2xl font-medium text-gray-700'>
                        Authentication with Appwrite and Nextjs 13
                    </h1>
                </div>
                <section className='flex justify-center'>
                    <div className='px-4 py-2 border rounded-lg w-full lg:w-2/4'>
                        <div className='border-b h-8 mb-4'>
                            <h3 className='text-gray-700'>
                                Sign up with your details
                            </h3>
                        </div>
                        <form onSubmit={handleSubmit}>
                            <fieldset>
                                <label className='text-sm text-gray-400 mb-4 block'>
                                    Name
                                </label>
                                <input
                                    name='name'
                                    className='border w-full rounded-sm mb-6 p-2'
                                    required
                                    value={value.name}
                                    onChange={handleChange}
                                    type='text'
                                />
                            </fieldset>
                            <fieldset>
                                <label className='text-sm text-gray-400 mb-4 block'>
                                    Email
                                </label>
                                <input
                                    name='email'
                                    className='border w-full rounded-sm mb-6 p-2'
                                    required
                                    value={value.email}
                                    onChange={handleChange}
                                    type='email'
                                />
                            </fieldset>
                            <fieldset>
                                <label className='text-sm text-gray-400 mb-4 block'>
                                    Password
                                </label>
                                <input
                                    name='password'
                                    className='border w-full rounded-sm mb-6 p-2'
                                    required
                                    value={value.password}
                                    onChange={handleChange}
                                    type='password'
                                />
                            </fieldset>
                            <button
                                className='text-sm text-white px-8 py-2 rounded-sm bg-blue-600 hover:bg-blue-700'
                                disabled={isLoading}
                            >
                                Sign up
                            </button>
                            <div className='flex mt-6'>
                                <p>Already have an account?</p>{' '}
                                <Link
                                    href='/signin'
                                    className='ml-2 text-blue-600 font-medium'
                                >
                                    Sign in
                                </Link>
                            </div>
                        </form>
                    </div>
                </section>
            </main>
        </div>
    );
}
```

**Authenticated page**

Lastly, you will modify the `page.js` file inside the `app` folder as shown below:

```js
'use client';
import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
import { getAccount, logout } from '../../utils/appwriteClient';

export default function Home() {
    const [session, setSession] = useState(null);
    const router = useRouter();
    const getSession = () => {
        getAccount()
            .then((res) => setSession(res))
            .catch((err) => {
                router.push('/signin');
                console.log(err);
            });
    };

    useEffect(() => {
        getSession();
    }, []);
    const signOut = () => {
        logout();
        alert('logout successful');
        router.push('/signin');
    };
    return (
        <div className='w-screen h-screen bg-white'>
            <main className='py-4 px-4 lg:py-10 lg:px-10 w-full'>
                <div className='flex justify-center mb-8'>
                    <h1 className='text-2xl font-medium text-gray-700'>
                        Welcome
                    </h1>
                </div>
                <section className='flex justify-center'>
                    <div className='px-4 py-2 border rounded-lg w-full lg:w-2/4'>
                        <h3 className='text-gray-700'>
                            Name: {session && session.name}
                        </h3>
                        <h3 className='text-gray-700 mt-4'>
                            Name: {session && session.email}
                        </h3>
                        <button
                            className='text-sm text-white px-8 py-2 rounded-sm bg-black hover:bg-gray-800 mt-6'
                            onClick={signOut}
                        >
                            Log out
                        </button>
                    </div>
                </section>
            </main>
        </div>
    );
}
```

The snippet above does the following:

-   Imports the required dependencies.
-   Creates states and route variables to manage logged-in user sessions and routes accordingly.
-   Creates a `getSession` function to get the logged-in user session and re-route to the login page if the session is empty.
-   Creates a `signOut` function to log the user out
-   Updates the UI to show logged-in user’s **name** and **email**

With that done, you can test the application by running the command below:

```bash
npm run dev
```

or 

```bash
yarn dev
```

![Demo 1](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExZmc1eDRlb20wcnZmczRhOGN6d2JiMXk5bmNlenRpOW0yajMyOWp4dCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/HJIHhWxQIJgSAFBIxo/giphy.gif)

![Demo 2](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExbGdqYzI0c28wa2QwZ2Zoc2YwcmZvY3JtcnY5czkxazduMjB5MnN1YSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/UAp8wpw0s5BS1tu0em/giphy.gif)

You can also validate the authenticated user details on the Appwrite console:

![Auth user](https://paper-attachments.dropboxusercontent.com/s_6EF4A6F48923F724F3C7B1650D1E95351534F1C48D7BEB524F67CA4F7DD6141E_1692065060014_Screenshot+2023-08-14+at+16.20.41.png)

## Conclusion

In conclusion, this post highlights how Appwrite provides an easy and secure way to manage authentication in Next.js applications. With [Appwrite](https://appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog), developers can quickly and easily establish authentication, manage users, and provide role-based access control to their applications.

## Resources

The following resources might be helpful:

-   [Appwrite Users API](https://appwrite.io/docs/server/users?sdk=nodejs-default#usersCreate)
-   [Next](https://nextjs.org/blog/next-13?utm_source=hackmamba&utm_medium=hackmamba-blog)[.js](https://nextjs.org/blog/next-13?utm_source=hackmamba&utm_medium=hackmamba-blog) [Version 13 Updates](https://nextjs.org/blog/next-13?utm_source=hackmamba&utm_medium=hackmamba-blog)
    [](https://nextjs.org/blog/next-13)- [Next](https://nextjs.org/docs/pages/building-your-application/routing/authenticating?utm_source=hackmamba&utm_medium=hackmamba-blog)[.js](https://nextjs.org/docs/pages/building-your-application/routing/authenticating?utm_source=hackmamba&utm_medium=hackmamba-blog) [Authentication](https://nextjs.org/docs/pages/building-your-application/routing/authenticating?utm_source=hackmamba&utm_medium=hackmamba-blog)
-   [Authentication with Appwrite](https://appwrite.io/docs/authentication?utm_source=hackmamba&utm_medium=hackmamba-blog)
    [](https://nextjs.org/docs/authentication)