Working with Cloudinary and Auth0 - Build a meme generator with React
Tags: cloudinary, auth0, react, jamstack
Published: 2021-10-19 23:12:09

Modern web development presents a number of issues, one of which is authentication, which is both critical and frequently overlooked. Authentication is often not implemented correctly resulting in major security breaches. 

This article aims to teach developers how to utilize user authentication to secure a React application with the help of [Auth0’s React SDK](https://github.com/auth0/auth0-react) which offers a high-level API for dealing with a variety of authentication related concerns while writing less code.

We will also use the cloud-based media management tools within -[Cloudinary](https://cloudinary.com/) to manage media-related assets needed.


##Prerequisites

To follow the steps in this article, we should have:

* Adequate knowledge of JavaScript and React.js.
* The latest version of Node.js installed.
* A terminal such as ITerm2(Mac OS) or Git bash (Windows).
* A Cloudinary account - Create one for free [here](https://cloudinary.com/homepage-2).
* An Auth0 account - Create one for free [here](https://auth0.com/).

If you need to look at the source code, it's available on [Github](https://github.com/ugwutotheeshoes/meme-gen) and [Codesandbox](https://codesandbox.io/s/solitary-smoke-in6s0?file=/src/index.js). Also see the deployed application on [Netlify](https://ug-meme-gen.netlify.app/).
**NOTE:** Because Codesandbox provides 2 different hosts with different URLs, open the app browser on Codesandbox in a new window for it to be authorized by Auth0. Click [here](https://in6s0.csb.app/) to access the app in a new window.


##Setting up our Cloudinary account

After successfully creating an account, Cloudinary will redirect to our account's dashboard page, where we can see account details that will be useful later on, including:

* Cloud Name
* API Key
* API Secret

**NOTE:** Do not share these details with anyone.


##Setting up our React Auth0 account

Once we sign in, Auth0 takes us to the [Dashboard](https://manage.auth0.com/). In the left sidebar menu, click on ["Applications"](https://manage.auth0.com/#/applications). Then, click the "Create Application" button. A modal opens up with a form to provide a name for the application and choose its type. Click on “Single Page Web Applications” as its type, then click on "Create".  Go to the "Settings" tab of your Auth0 Application page and fill the following with our localhost URL(`http://localhost:3030`):

- Allowed Callback URLs - A list of URLs that will be called back when the user authenticates.
- Allowed Logout URLs - A list of valid URLs to redirect to after logging out of Auth0.
- Allowed Web Origins - Comma-separated list of allowed origins for use with Cross-Origin Authentication.

Scroll down and click the "Save Changes" button.

From the Auth0 Application Settings page, we will need the Auth0 Domain and Client ID values later.
**NOTE:** Do not share these details with anyone.


##Installing the project dependencies

Next, create a react app and move into the app directory:

```javascript
npx create-react-app meme-gen
cd meme-gen
```
After that install `react-router-dom`, `cloudinary`, and `Auth0` with the following commands:

```javascript
#install react-router-dom, cloudinary and Auth0 for React SDK
npm install react-router-dom
npm install cloudinary-react
npm install @auth0/auth0-react
```

Running `npm start` should render an app with an affirmative message on our browser:

![React App](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v1x4876ct302x0nkgcwd.png)


#Defining our components

While still in development, replace the default syntax in `App.js` with this:

```javascript
import React, { useState } from 'react';
import './App.css';
    
function App() {
  return (
      <main className="main">
        <div className="title">
          <h2>meme generator</h2>
        </div>
      </main>
     );
   }
export default App;
``` 

##Generating sample data

Next, we will need to create and fill a `Data.js` file with the URL of our images; here's a sample of the data we will be using:

```javascript
const memes = [
 {
   id: 1,
   img: 'meme/livingroom.jpg',
  },
 { 
   id: 2,
   img: 'meme/tiktok.jpg',
  },
 {
   id: 3,
   img: 'meme/flush.jpg',
  },
 {
   id: 4,
   img: 'meme/million.jpg',
  },
 {
   id: 5,
   img: 'meme/wiki.jpg',
  }
];
export default memes;
```

Create a file and define two `useState` variables to:

* Access data from `Data.js` 
* Set the index of our data, with an initial value of 0.

Using the Cloudinary elements from the `cloudinary-react` library, import the necessary images from Cloudinary, then apply the Cloud name from our account details and also include the name of the image in the `Image` component:

```javascript
import {Image, Transformation, CloudinaryContext} from 'cloudinary-react';
    
<CloudinaryContext cloudName="your-cloud-name">
  <Image publicId="img" alt="profile">
    
  </Image>
</CloudinaryContext>
```

Then, we will create a function that generates a random number for each image. This function is assigned to the index state variable and is updated every time we click on the button. We also need to make sure the random number generated is not higher than the data length in `Data.js`.

```javascript
const [index, setIndex] = useState(0);
const {img} = memes[index];
    
const checkNumber = (number) => {
    if (number > memes.length - 1){
      return 0
    }
    if (number < 0){
      return memes.length - 1
    }
    return number;
  }
    
const randomMeme = () =>{
let randomNumber = Math.floor(Math.random() * memes.length);
    if(randomNumber === index){
      randomNumber = index + 1;
    }
    setIndex(checkNumber(randomMeme));
  }
```


#Setting up the Auth0 React SDK

##Configuring the `Auth0Provider` component

Next, we will need to build a feature to prevent unauthorized access to the app.
Create a `.env` file to store the Client ID and Domain stated earlier on, then create another file. 

```javascript
#.env
REACT_APP_AUTH0_DOMAIN = THE-DOMAIN-NAME
REACT_APP_AUTH0_CLIENT_ID = THE-CLIENT-ID
```

Then, install [DotEnv](https://www.npmjs.com/package/dotenv) using the command: 

```javascript
npm install dotenv
```

Then in our app, require and configure the package like this: 

```javascript
require('dotenv').config()
```

The DotEnv npm package automatically loads environment variables from a `.env` file into the `process.env` object.
The `Auth0Provider` component is imported from the `@auth0/auth0-react` SDK library to store the authentication state of our users and the state of the SDK — whether Auth0 is ready to use or not.
Next, we will wrap our root component, such as `App` in the `index.js` file to integrate Auth0 with our React app:

```javascript
#index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { Auth0Provider } from "@auth0/auth0-react";

require("dotenv").config();
const domain = process.env.REACT_APP_AUTH0_DOMAIN;
const clientId = process.env.REACT_APP_AUTH0_CLIENT_ID;

ReactDOM.render(
  <Auth0Provider
    domain={domain}
    clientId={clientId}
    redirectUri={window.location.origin}
  >
    <App />
  </Auth0Provider>,
  document.getElementById("root")
);
```

##User Authentication

Create a `login-button.js` file to handle the log in feature of the app. This makes use of `loginWithRedirect()` method which prompts a user to authenticate before the user can access the app. If the user does not have a Auth0 account, a sign up option is made available by Auth0 React SDK.

```javascript
import React from "react";
const LoginButton = ({ loginWithRedirect }) => {
  return (
    <button className="login" onClick={() => loginWithRedirect()}>
      Log In
    </button>
  );
};
export default LoginButton;
```  

We also need a log out feature, create a `logout-button.js` file which makes use of `logout()`method which clears the application session and redirects a user to the log in page.

```javascript
import React from "react";
const LogoutButton = ({ logout }) => {
   return (
    <button className="logout" onClick={() => logout()}>
      Log Out
    </button>
  );
};
export default LogoutButton;
```   

Finally, we will use conditional rendering in the `App.js` to show the app when Auth0 has authenticated the user and display an error saying "Log in to gain access to the application" when it has not.

#Video

{% youtube PwYHBh8iPT8 %}

#Conclusion

This tutorial covered the most common authentication use case for a React application. It shows that with the help of Auth0, we don't need to be an expert on identity protocols to understand how to secure a web application.

For references, check out:

* [Auth0 Documentation](https://auth0.com/docs/)
* [Cloudinary Documentation](https://cloudinary.com/documentation)

Content created for the [Hackmamba](https://content.hackmamba.io/) Jamstack Content Hackathon with [Auth0](https://auth0.com/) and [Cloudinary](https://cloudinary.com/).