Setting up Firebase Authentication in React Application
Tags: react, javascript, beginners, webdev
Published: 2020-09-14 07:40:34

In this tutorial we’ll be building a simple react application with authorization using Firebase with private routes. Before we dig in to the details, i would like to mention about some ready to use best react dashboard templates by [WrapPixel](https://www.wrappixel.com/templates/category/react-templates/?ref=232) and web application templates by [AdminMart](https://adminmart.com/templates/react/?ref=232), which comes with Firebase Authentication.

You can check them out and use directly in your project to save lots of time and money, also they are built by experienced developers, so you get chance to learn a lots as well.

Let’s now move to our tutorial.

## Contents
- Introduction
- Prerequisites
- Setting up React
- Setting up Firebase in React
- React Router
- Authentication Context using Firebase and React
- Private Routes in React
- Create View Components in React
    - Signup in Firebase
    - Sign in Firebase
    - SignOut in Firebase
- Conclusion


## Introduction

We use authentication to recognizing a user’s identity. At the end of this article, we’ll have built a simple React application that allows users to authenticate using Firebase and we’ll make sure that only authenticated users can access the application.

## Prerequisites
- Have basic knowledge of Javascript
- Make sure you have Node>=8.10 and npm>=5.6 on your machine for better experience
- Have basic understanding of React, Context, Hooks, Routes.
- Comfortable with command line 
- Text editor
- A Firebase account

## Setting up React

To create a project in React run the command bellow:

    npx create-react-app react_firebase_auth

**npx** is a package runner tool that comes with npm 5.2+.  We just created a project named **react_firebase_auth**. Go to the project and start it.


    cd react_firebase_auth
    npm start

We will need some dependecies for our application such as:

- **react-dom**  that contains the **DOM** bindings for **React Router**, I mean, the **router** components for websites.


    npm install --save react-router-dom


- **material-ui** to implement Google’s Material Design.


    npm i @material-ui/core --save

Our react application was setuped successfully. Now it’s time to setup the firebase.


## Setting up Firebase in React

Let’s begin by creating a new firebase application. To this follow the steps bellow.
Go to [Firebase console](https://console.firebase.google.com/).

1. Press Add Project
2. Enter your app name
3. Accept the terms
4. Press Create Project
5. Wait untill the ap will be created
6. And press Continue
7. Go to Authentication tap
8. Click Set up sign-in methods
9. Chosse email/password and enable it.
10. After it is done go to Project Settings and scroll down to the list of platforms. Select Web.
11. Copy your app configuration


![Javascript Config](https://www.wrappixel.com/demos/images/javascript-config.jpg)


On side bar menu click **Authentication**, go to Sign-in method and enable **email/password**.

Now let’s setup firebase in our react application. Create **firebase.js** file in your **src** folder.
Install firebase dependecie using the command bellow:

    npm install --save firebase

Open **firebase.js** and paste the javascript script that you copied in the Firebase Console.

![firebase.js](https://www.wrappixel.com/demos/images/firebase-js.jpg)


As you can see, we can iniliaze our firebase app using firebase.initializeApp  and exported it as **app**. Doing so, we have total access to our database.


## React Router

Now, go to your **App.js** and add some routing.

    import React from 'react';
    import "./App.css";
    import { BrowserRouter as Router, Route } from "react-router-dom";
    import Home from './Home'
    import Login from './Login'
    import SignUp from './Signup'
    function App() {
      return (
        <Router>
            <div>
              <Route exact path="/" component={Home} />
              <Route exact path="/login" component={Login} />
              <Route exact path="/signup" component={SignUp} />
            </div>
          </Router>
      );
    }
    export default App;

We wrapped our layout into **BrowserRouter** that provides Browser Context to all our application. Basically it allows us to use Routes, Links, Redirects and other routers features.

Now, to work with authentication we will need to have to store our authentication states if you’re logged in or not and update our component tree. To do this we’ll use React Context API. 


## Authentication Context using Firebase and React

 Create **Authentication.js** in your **scr** folder and past this:
```
     import React, { useEffect, useState } from "react";
    import app from "./firebase.js";
    export const AuthContext = React.createContext();
    export const AuthProvider = ({ children }) => {
      const [currentUser, setCurrentUser] = useState(null);
      const [pending, setPending] = useState(true);
      useEffect(() => {
        app.auth().onAuthStateChanged((user) => {
          setCurrentUser(user)
          setPending(false)
        });
      }, []);
      if(pending){
        return <>Please wait...</>
      }
      return (
        <AuthContext.Provider
          value={{
            currentUser
          }}
        >
          {children}
        </AuthContext.Provider>
      );
    };
```
In this file we had to import **app** from firebase.js where we have our firebase API and we created a context. Context in react is everthing that allows you to propagate some data to the whole react component tree.

And we created a provider component that let’s you store our **authentication state**. It holders an user and we will update evertime our authentication states will change in firebase. For this we use hook, **useEffect**, to signup for changes to our firebase object and we pass an empty array to our **useEffect** as a second argument so that it will run once when component **AuthProvider** will be mounted in our tree.

Then in our **AuthProvider** layout we used AuthProvider.Provider and we passed our current user that we get from firebase on **every auth state change**, we passed it as a value to our **AuthProvider.Provider** and then we render **children** passed to this component.

Now, go back to App.js and wrap our layout into **AuthProvider**.

        <AuthProvider>
          <Router>
            <div>
              <Route exact path="/" component={Home} />
              <Route exact path="/login" component={Login} />
              <Route exact path="/signup" component={SignUp} />
            </div>
          </Router>
        </AuthProvider>

So, everthing bellow it in our component tree will have access to current user through the context API. In our case if you’re logged in you’ll have user object having all the user description and if you´re logged out  you’ll have null or undefined state user object.


## Private Routes in React

We can create our privates routes to allow only the authenticated users can go to the home page.

Create PrivateRoute.js in your **scr** folder.

    import React, { useContext } from "react";
    import { Route, Redirect } from "react-router-dom";
    import { AuthContext } from "./Authentication";
    const PrivateRoute = ({ component: RouteComponent, ...rest }) => {
      const {currentUser} = useContext(AuthContext);
      return (
        <Route
          {...rest}
          render={routeProps =>
            !!currentUser ? (
              <RouteComponent {...routeProps} />
            ) : (
              <Redirect to={"/login"} />
            )
          }
        />
      );
    };
    
    export default PrivateRoute

Here we need to know what component should be render if user is authenticated. So we take component and the rest of the props { component: RouteComponent, ...rest }. 
**PrivateRouter** wil be basically a wrapper on regular routes. So we pass the rest of the props {...rest} and then in our **route render function**, depending if we have user or not, we will render our **route component** or **redirect to login page**.

Go back to your **App.js** and make these changes:

     <AuthProvider>
          <Router>
             <div>
               <PrivateRoute exact path="/" component={Home} />
               <Route exact path="/signin" component={Signin} />
               <Route exact path="/signup" component={SignUp} />
            </div>
          </Router>
      </AuthProvider>

Now let’s create our view components. We’ll use material UI for this. To get more deeper about Material-UI you can click [here](https://material-ui.com/) to get it done, using the official documentation.


## Create View Components in React

We’ll use materil-ui for our interfaces. Make sure you have installed the material-ui dependecie.

NOTE: In this article we’re covering the Firebase Authentication. So, for more details about **material-ui** go to [official documentation](https://material-ui.com/).

Create **SignIn.js** in your **src** folder and past the code bellow.


    import React from 'react';
    import Button from '@material-ui/core/Button';
    import CssBaseline from '@material-ui/core/CssBaseline';
    import TextField from '@material-ui/core/TextField';
    import FormControlLabel from '@material-ui/core/FormControlLabel';
    import Checkbox from '@material-ui/core/Checkbox';
    import Grid from '@material-ui/core/Grid';
    import Box from '@material-ui/core/Box';
    import Typography from '@material-ui/core/Typography';
    import { makeStyles } from '@material-ui/core/styles';
    import Container from '@material-ui/core/Container';
    
    import { Link } from 'react-router-dom'
    function Copyright() {
      return (
        <Typography variant="body2" color="textSecondary" align="center">
          {'Copyright © '}
          <Link color="inherit" href="https://pacoconsulting.co.mz/">
            PACO IT Consulting
          </Link>{' '}
          {new Date().getFullYear()}
          {'.'}
        </Typography>
      );
    }
    const useStyles = makeStyles((theme) => ({
      paper: {
        marginTop: theme.spacing(8),
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
      },
      avatar: {
        margin: theme.spacing(1),
        backgroundColor: theme.palette.secondary.main,
      },
      form: {
        width: '100%', // Fix IE 11 issue.
        marginTop: theme.spacing(1),
      },
      submit: {
        margin: theme.spacing(3, 0, 2),
      },
    }));
    export default function SignIn() {
      const classes = useStyles();
      return (
        <Container component="main" maxWidth="xs">
          <CssBaseline />
          <div className={classes.paper}>
            <Typography component="h1" variant="h5">
              Sign in
            </Typography>
            <form onSubmit={handleLogin}  className={classes.form} noValidate>
              <TextField
                variant="outlined"
                margin="normal"
                required
                fullWidth
                id="email"
                label="Email Address"
                name="email"
                autoComplete="email"
                autoFocus
              />
              <TextField
                variant="outlined"
                margin="normal"
                required
                fullWidth
                name="password"
                label="Password"
                type="password"
                id="password"
                autoComplete="current-password"
              />
              <FormControlLabel
                control={<Checkbox value="remember" color="primary" />}
                label="Remember me"
              />
              <Button
                type="submit"
                fullWidth
                variant="contained"
                color="primary"
                className={classes.submit}
              >
                Sign In
              </Button>
              <Grid container>
                <Grid item xs>
                  <Link href="#" variant="body2">
                    Forgot password?
                  </Link>
                </Grid>
                <Grid item>
                  <Link href="#" variant="body2">
                    {"Don't have an account? Sign Up"}
                  </Link>
                </Grid>
              </Grid>
            </form>
          </div>
          <Box mt={8}>
            <Copyright />
          </Box>
        </Container>
      );
    }


Create **SignUp.js** in your scr folder.

       import React from 'react';
    import Button from '@material-ui/core/Button';
    import CssBaseline from '@material-ui/core/CssBaseline';
    import TextField from '@material-ui/core/TextField';
    import FormControlLabel from '@material-ui/core/FormControlLabel';
    import Checkbox from '@material-ui/core/Checkbox';
    import Grid from '@material-ui/core/Grid';
    import Box from '@material-ui/core/Box';
    import Typography from '@material-ui/core/Typography';
    import { makeStyles } from '@material-ui/core/styles';
    import Container from '@material-ui/core/Container';
    import { Link } from 'react-router-dom'
    function Copyright() {
      return (
        <Typography variant="body2" color="textSecondary" align="center">
          {'Copyright © '}
          <Link color="inherit" href="https://material-ui.com/">
            Your Website
          </Link>{' '}
          {new Date().getFullYear()}
          {'.'}
        </Typography>
      );
    }
    const useStyles = makeStyles((theme) => ({
      paper: {
        marginTop: theme.spacing(8),
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
      },
      avatar: {
        margin: theme.spacing(1),
        backgroundColor: theme.palette.secondary.main,
      },
      form: {
        width: '100%', // Fix IE 11 issue.
        marginTop: theme.spacing(3),
      },
      submit: {
        margin: theme.spacing(3, 0, 2),
      },
    }));
    export default function SignUp() {
      const classes = useStyles();
    
      return (
        <Container component="main" maxWidth="xs">
          <CssBaseline />
          <div className={classes.paper}>
            <Typography component="h1" variant="h5">
              Sign up
            </Typography>
            <form onSubmit={handleSignUp} className={classes.form} noValidate>
              <Grid container spacing={2}>
                <Grid item xs={12} sm={6}>
                  <TextField
                    autoComplete="fname"
                    name="firstName"
                    variant="outlined"
                    required
                    fullWidth
                    id="firstName"
                    label="First Name"
                    autoFocus
                  />
                </Grid>
                <Grid item xs={12} sm={6}>
                  <TextField
                    variant="outlined"
                    required
                    fullWidth
                    id="lastName"
                    label="Last Name"
                    name="lastName"
                    autoComplete="lname"
                  />
                </Grid>
                <Grid item xs={12}>
                  <TextField
                    variant="outlined"
                    required
                    fullWidth
                    id="email"
                    label="Email Address"
                    name="email"
                    autoComplete="email"
                  />
                </Grid>
                <Grid item xs={12}>
                  <TextField
                    variant="outlined"
                    required
                    fullWidth
                    name="password"
                    label="Password"
                    type="password"
                    id="password"
                    autoComplete="current-password"
                  />
                </Grid>
                <Grid item xs={12}>
                  <FormControlLabel
                    control={<Checkbox value="allowExtraEmails" color="primary" />}
                    label="I want to receive inspiration, marketing promotions and updates via email."
                  />
                </Grid>
              </Grid>
              <Button
                type="submit"
                fullWidth
                variant="contained"
                color="primary"
                className={classes.submit}
              >
                Sign Up
              </Button>
              <Grid container justify="flex-end">
                <Grid item>
                  <Link to="/signin" variant="body2">
                    Already have an account? Sign in
                  </Link>
                </Grid>
              </Grid>
            </form>
          </div>
          <Box mt={5}>
            <Copyright />
          </Box>
        </Container>
      );
    }

Create **Home.js** in your scr folder.

    import React from 'react';
    import { makeStyles } from '@material-ui/core/styles';
    import AppBar from '@material-ui/core/AppBar';
    import Toolbar from '@material-ui/core/Toolbar';
    import Typography from '@material-ui/core/Typography';
    import Button from '@material-ui/core/Button';
    import IconButton from '@material-ui/core/IconButton';
    import MenuIcon from '@material-ui/icons/Menu';
    const useStyles = makeStyles((theme) => ({
      root: {
        flexGrow: 1,
      },
      menuButton: {
        marginRight: theme.spacing(2),
      },
      title: {
        flexGrow: 1,
      },
    }));
    export default function ButtonAppBar() {
      const classes = useStyles();
      return (
        <div className={classes.root}>
          <AppBar position="static">
            <Toolbar>
              <IconButton edge="start" className={classes.menuButton} color="inherit" aria-label="menu">
                <MenuIcon />
              </IconButton>
              <Typography variant="h6" className={classes.title}>
                News
              </Typography>
              <Button color="inherit">Login</Button>
            </Toolbar>
          </AppBar>
        </div>
      );
    }
## Signup in Firebase

In **SignUp.js** file make these changes:

    import React, { useCallback} from "react";
    import { Link } from 'react-router-dom'
    import app from "./firebase.js";

And

    export default function SignUp({ history }) {
      const classes = useStyles();
      const handleSignUp = useCallback(async event => {
        event.preventDefault();
        const { email, password } = event.target.elements;
        try {
          await app
            .auth()
            .createUserWithEmailAndPassword(email.value, password.value);
          history.push("/");
        } catch (error) {
          alert(error);
        }
      }, [history]);
    ...
    ...
    ...

This component is getting **history** object from our routing context.  When we click on that button our  **handleSignUp** will fire. Inside this function we get our event and calll **preventDefault()** because we want to reload the page when user clicks on signup button. Then we get out email and password inputs from **target.elements** and we call **createUserWithEmailAndPassword()** from firebase API and we pass our **email** and **password** values: **createUserWithEmailAndPassword(email.value, password.value)**.
And then we pass our **handleSignUp**  function to **onSubmit** callback of our form.

---

### Sponsored:

[![React](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6be3k0c5qa8udbdbqcsx.jpg)](https://adminmart.com/templates/react/?ref=6)

---

## Sign in Firebase

In the **SignIn.js** file, SignIn.js make these imports:

    import React, { useCallback, useContext } from 'react'; // add {useCallback, useContext}
    import { withRouter, Redirect } from "react-router";
    import app from "./firebase.js";
    import { AuthContext } from "./Authentication.js";

In the **SignIn()** function make these changes:

- Add history
- Add  handleLogin method.
    export default function SignIn({history}) {
      const classes = useStyles();
      const handleLogin = useCallback(
        async event => {
          event.preventDefault();
          const { email, password } = event.target.elements;
          try {
            await app
              .auth()
              .signInWithEmailAndPassword(email.value, password.value);
            history.push("/");
          } catch (error) {
            alert(error);
          }
        },
        [history]
      );
      const { currentUser } = useContext(AuthContext);
      if (currentUser) {
        return <Redirect to="/" />;
      }
    ...
    ...
    ...
    ...

There are two differences with SignUp page. Here we use **signInWithEmailAndPassword()** and we use our authentication context` const { currentUser } = useContext(AuthContext);` . As you migth have remember we are tracking firebase user and we update our context with currentUser field using our auth model. And then we check: if we have currentUser we render Redirect component from react router. This component when rendered will just redirect to path that use set in the **to** attribute.


## SignOut in Firebase

 
 Basically, in **Home.js** we call  **signOut()** from **auth** module in our logout button.

    onClick={() => app.auth().signOut()} 


Congratulations!!! Test your app.

    npm start

# Conclusion

![Output](https://www.wrappixel.com/wp-content/uploads/2020/09/overview-authentication.gif)

Our application is ready. Now you’re able to use Firebase Authentication in your React application.
 
 Thanks for reading!