Create a passwordless authentication using Auth0, Cloudinary and Nextjs
Tags: cloudinary, hackjamstack, auth0, jamstack
Published: 2021-10-17 09:42:45

---
title: Create a passwordless authentication using Auth0, Cloudinary and Nextjs
published: true
description: 
tags: #cloudinary, #hackjamstack, #auth0, #JamStack
---

Passwordless authentication is an authentication method that allows users to log in without remembering a password. Instead, it requires users to enter public identifiers like username, phone number, email e.t.c and receive a one-time code or link, which they can then use to log in.

In this post, we will discuss how to build a passwordless coupon generation app using [Cloudinary](https://cloudinary.com/), [Auth0](https://auth0.com/), and [Next.js](https://nextjs.org/). At the end of this tutorial, we would have learnt how to build a secure application using Auth0, Cloudinary and Next.js.


**Source code**

You can find the source code of this project [here](https://github.com/Mr-Malomz/auth_pwdless).

# Prerequisites

The next steps in this post require JavaScript and React.js experience. Experience with Next.js isn’t a requirement, but it’s nice to have.

We also need the following:

- A [Cloudinary account](https://cloudinary.com/) for file hosting. [**Signup**](https://cloudinary.com/users/register/free) **is completely free**.
- An [Auth0 account](https://auth0.com/) for authentication. [**Signup**](https://auth0.com/signup?place=header&type=button&text=sign%20up) **is completely free**.
- A [CodeSandbox](http://codesandbox.com/) account. [**Signup**](http://codesandbox.com/) **is completely free**.

## Getting Started

We need to create a Next.js starter project by navigating to the desired directory and running the command below in our terminal


    npx create-next-app auth_pwdless && cd auth_pwdless

This command creates a Next.js project called `auth_pwdless` and navigates into the project directory.

We proceed to install the required dependencies with:


    npm install cloudinary-react auth0-js

`cloudinary-react` is a [library](https://github.com/cloudinary/cloudinary-react#readme) that handles rendering of media files.

`auth0-js` is a [library](https://github.com/auth0/auth0.js#readme) for managing client-side authentication.

# Setting up Passwordless functionality on Auth0
## Creating an Application

To get started, we need to log into our [Auth0](https://auth0.com/auth/login) dashboard. Click on **Applications**

![Auth0 Dashboard](https://paper-attachments.dropbox.com/s_39889F3A941E007B2BE724DE6F2C4C4FFE6C2B007CCCDB3B36F915067C40E3D1_1633445331548_Screenshot+2021-10-05+at+15.44.55.png)


In the application page, click on the **Create Application** button, input application name `auth_pwdless` in our case, select **Single Page Web Application** as the application type and **Create**

![creating app](https://paper-attachments.dropbox.com/s_92805FED2D981D79B86FF452AD4C2AB3F80EA63850F0C154653F5111C1E5C74F_1633741349305_Screenshot+2021-10-08+at+20.35.14.png)


Click on the **Settings** tab and copy the **Domain** and **Client ID**. They will come in handy when configuring Auth0.

![app configuration](https://paper-attachments.dropbox.com/s_92805FED2D981D79B86FF452AD4C2AB3F80EA63850F0C154653F5111C1E5C74F_1633742207801_Screenshot+2021-10-08+at+20.00.25.png)


Then scroll down to the **Applications URIs** section and fill in the details below for **Allowed Callback URLs, Allowed Logout URLs, Allowed Web Origins,** and **Allowed Origins (CORS)** respectively. 


> **PS:** For security reasons, Auth0 does not allow the use of URLs like `http://localhost:3000/` and `http://127.0.0.1:3000/`. We will be using the custom URL CodeSandbox provides. Auth0 also supports custom domains.


- Allowed Callback URLs
    - `https://ueofp.sse.codesandbox.io/coupon`. The `coupon` at the end of this URL represents the page in our application.
- Allowed Logout URLs, Allowed Web Origins, and Allowed Origins (CORS)
    - `https://ueofp.sse.codesandbox.io/`
![URI](https://paper-attachments.dropbox.com/s_92805FED2D981D79B86FF452AD4C2AB3F80EA63850F0C154653F5111C1E5C74F_1633743206535_Screenshot+2021-10-09+at+02.33.14.png)


Then scroll down to the bottom of the page and click on the **Save Changes** button.

## Setting up Passwordless

With the application configured, click on the **Authentication** and select **Passwordless**.
Then select **Email** authentication type.

![auth method](https://paper-attachments.dropbox.com/s_92805FED2D981D79B86FF452AD4C2AB3F80EA63850F0C154653F5111C1E5C74F_1633743842260_Screenshot+2021-10-08+at+19.55.39.png)


Next, edit the **From Field**, **Subject Field** and **Save**. Auth0 also support custom settings like the email template format, OTP validity period, e.t.c.

![configure OTP Email](https://paper-attachments.dropbox.com/s_92805FED2D981D79B86FF452AD4C2AB3F80EA63850F0C154653F5111C1E5C74F_1633743886656_Screenshot+2021-10-08+at+20.03.15.png)


Next, connect the `auth_pwdless` app we created earlier and **Save**.

![Connecting app](https://paper-attachments.dropbox.com/s_92805FED2D981D79B86FF452AD4C2AB3F80EA63850F0C154653F5111C1E5C74F_1633744165149_Screenshot+2021-10-08+at+20.03.38.png)


Finally, we can test the application by clicking on the **Try** button and then check our mail for the one-time-password(OTP).

![Try Passwordless](https://paper-attachments.dropbox.com/s_92805FED2D981D79B86FF452AD4C2AB3F80EA63850F0C154653F5111C1E5C74F_1633744300199_Screenshot+2021-10-08+at+20.04.46.png)

# Integrating Passwordless with Auth0

First, we can leverage Next.js [CSS Module](https://github.com/css-modules/css-module) support to style our page by replacing the content in `Home.module.css` in the `styles` folder with the gist below:

{% gist https://gist.github.com/Mr-Malomz/1675c4bd4595b2bef2ad3a19258bc311 %}

With that done, we need to create an helper function to help us instantiate Auth0. Create a a `config` folder in the project root directory and, in the folder, create an `auth.js` file and add the code snippet below.


   ```javascript 
import { WebAuth } from "auth0-js";
    export const webAuth = new WebAuth({
      clientID: <YOUR_CLIEND_ID HERE>,
      domain: <YOUR DOMAIN HERE>,
      redirectUri: 'https://ueofp.sse.codesandbox.io/coupon',//replace with your codesandbox url
      responseType: "token"
    }); 
```

The `webAuth` variable creates an instance of the `WebAuth` class and configures it with `clientID`, `domain`, `redirectUri` and `responseType`.

## Setting up Login

Next, we need to modify `index.js` file in the `pages`  folder by importing the `webAuth` variable to create `handleAuth` and `handleVerifyToken` functions to send OTP to specified email and verify the OTP.

```javascript
    import styles from "../styles/Home.module.css";
    import { useState } from "react";
    import { useRouter } from "next/dist/client/router";
    import { webAuth } from "../config/auth";
    
    export default function Home() {
      const router = useRouter();
      const [email, setEmail] = useState("");
      const [otp, setOtp] = useState("");
      const [error, setError] = useState({
        emailError: false,
        otpError: false
      });
      const [success, setSuccess] = useState(false);
      const handleAuth = (e) => {
        e.preventDefault();
        webAuth.passwordlessStart(
          {
            connection: "email",
            send: "code",
            email: email
          },
          function (err, res) {
            if (res.Id) {
              setSuccess(true);
            } else {
              setError({ ...error, emailError: true });
            }
          }
        );
      };
    
      const handleVerifyToken = (e) => {
        e.preventDefault();
        webAuth.passwordlessLogin(
          {
            connection: "email",
            email: email,
            verificationCode: otp
          },
          function (err, res) {
            if (err) {
              setError({ ...error, otpError: true });
            } else {
              router.push("/coupon");
            }
          }
        );
      };
      return (
        <div className={styles.container}>
          {/* remaining JSX comes here */}
        </div>
      );
    }
```

The snippet above does the following:

- Import required dependencies
- Create states to manage email, OTP, errors and success.
- `handleAuth` configures how the OTP will be sent(email), the type of OTP to be sent(code) and the email to which the OTP will be sent.
- `handleVerifyToken` configures how the OTP will be sent(email), the user's email to which the OTP is delivered, and the code sent to the user. The function also routes the user to the `coupon` page if the OTP is valid. We will create this page shortly.

Then we need to include markups to conditionally display forms to request for OTP and  verify OTP as shown below:

```javascript
    //imports here
    
    export default function Home() {
      //states here
    
      const handleAuth = (e) => {
        //send token code here
      };
    
      const handleVerifyToken = (e) => {
        //verify token code here
      };
      return (
        <div className={styles.container}>
          {!success && (
            <form onSubmit={handleAuth}>
              <input
                type="email"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                className={styles.input}
                placeholder="enter email"
                required
              />
              <button className={styles.button}>Get Coupon</button>
              {error.emailError && (
                <p className={styles.error}>Error sending mail</p>
              )}
            </form>
          )}
          {success && (
            <form onSubmit={handleVerifyToken}>
              <input
                type="number"
                value={otp}
                onChange={(e) => setOtp(e.target.value)}
                className={styles.input}
                placeholder="input token"
                required
              />
              <button className={styles.button}>Verify Token</button>
              {error.otpError && (
                <p className={styles.error}>Error validating OTP</p>
              )}
            </form>
          )}
        </div>
      );
    }
```

**Complete index.js**

{% gist https://gist.github.com/Mr-Malomz/66a1fccb77060a29dce0dccd6ec47ca6 %}

## Setting up the coupon page

With the authentication setup, we need to create a `coupon.js` file inside the `pages` folder, and in this file, add the code snippet below:

```javascript
    import React from "react";
    import { CloudinaryContext, Transformation, Image } from "cloudinary-react";
    import styles from "../styles/Home.module.css";
    
    export default function Coupon() {
      return (
        <div className={styles.container}>
          <p>
            Congratulations {user && user.email}
            <span role="img" aria-label="emoji">
              🎉
            </span>
          </p>
          <h1>
            Coupon: {Math.floor(Math.random() * (67646676 - 6746 + 1)) + 74664}
          </h1>
          <CloudinaryContext cloudName="dtgbzmpca">
            <Image publicId="v1633726853/tamanna-rumee-rOBRka7Q12U-unsplash.jpg">
              <Transformation
                crop="scale"
                width="600"
                height="400"
                dpr="auto"
                responsive_placeholder="blank"
              />
            </Image>
          </CloudinaryContext>
        </div>
      );
    }
```

The `Coupon` page uses the `Math` object to generate random numbers as coupons and `cloudinary-react` to optimize and transform a congratulatory sample image.

Finally, we need to protect our page using Auth0 as we want only users with OTP to access the coupon.  

```javascript
    //remaining import comes here
    import { useState, useEffect } from "react"; //add
    import { webAuth } from "../config/auth"; //add
    import { useRouter } from "next/dist/client/router"; //add
    
    export default function Coupon() {
      const [user, setUser] = useState(null);
      const router = useRouter();
    
      useEffect(() => {
        if (window.location.hash) {
          webAuth.parseHash({ hash: window.location.hash }, function (
            err,
            authResult
          ) {
            if (err) {
              return console.log(err);
            }
            webAuth.client.userInfo(authResult.accessToken, function (err, user) {
              // get user info
              setUser(user);
            });
          });
        } else {
          if (user === null) {
            router.push("/");
          }
        }
      }, []);
    
      return (
        <div className={styles.container}>
          <p>
            Congratulations {user && user.email} {/* modify this to show email*/}
            <span role="img" aria-label="emoji">
              🎉
            </span>
          </p>
          {/* remaining JSX comes here */}
        </div>
      );
    }
```

The updated snippet above does the following:

- Import required dependencies.
- Creates state to manage authenticated users.
- Use `webAuth` variable created earlier to parse URL hash fragment sent by Auth0 when redirecting to the `Coupon` page and get the `user`’s information. Then, we use the `user` information to render the `Coupon` page when valid or redirect to the `Home` page when it is not.
- Display user’s email.

**Complete coupon.js**

{% gist https://gist.github.com/Mr-Malomz/be2645824088ab4dffcf639d01d70330 %}

Finally, we can test our application by requesting OTP, checking specified email, verifying OTP and getting a coupon.

![send OTP](https://paper-attachments.dropbox.com/s_92805FED2D981D79B86FF452AD4C2AB3F80EA63850F0C154653F5111C1E5C74F_1633775830692_Screenshot+2021-10-09+at+11.31.56.png)
![Verify OTP](https://paper-attachments.dropbox.com/s_92805FED2D981D79B86FF452AD4C2AB3F80EA63850F0C154653F5111C1E5C74F_1633775830702_Screenshot+2021-10-09+at+11.32.53.png)



![getting coupon](https://paper-attachments.dropbox.com/s_92805FED2D981D79B86FF452AD4C2AB3F80EA63850F0C154653F5111C1E5C74F_1633775860533_Screenshot+2021-10-09+at+11.33.47.png)



# Conclusion

This post discussed how to build a secure passwordless coupon generation app using Cloudinary, Auth0, and Next.js.

You may find these resources useful:

- [Auth0 passwordless authentication](https://auth0.com/docs/libraries/auth0js#passwordless-login)
- [Auth0.js library](https://github.com/auth0/auth0.js)
- [Cloudinary react library](https://github.com/cloudinary/cloudinary-react)

Content created for the [Hackmamba](https://content.hackmamba.io/) Jamstack Content Hackathon.