In this lesson we’re going to add and set up authentication into the application, so we can manage user logins and registrations.

But first, let me do a little bit of analysis here.

What’s the authentication story of our application? Let’s talk about it.

We’re going to use a local database to store our users data (no Firebase, Auth0 or other cloud-based solutions).

We are NOT going to use OAuth (which serves a different purpose) or JWT tokens (which are better suited for API access tokens).

We’ll use what I believe is the most sensible solution to a simple authenticaiton strategy: server based sessions, stored in HTTP-only cookies.

First, we’re going to add an API route to the Next.js application.

By convention Next.js considers a server route any JavaScript file under pages/api/.

Create the file pages/api/auth/register.js. In there, we initialize and export a function:

pages/api/auth/register.js

export default (req, res) => {

}

I only want to respond to POST requests, so we filter out requests that do not have this HTTP method:

pages/api/auth/register.js

export default (req, res) => {
  if (req.method !== 'POST') {
    res.status(405).end() //Method Not Allowed
    return
  }
  console.log('POST request received')
}

We’ll now use Axios to POST to this route to create a new user.

Open components/RegistrationModal.js.

We create 3 state properties in the component, add we’ll bind them to the form elements.

Let’s first transform

components/RegistrationModal.js

export default props => (
  <>
    ...
  </>
)

to

components/RegistrationModal.js

export default props => {
  return (
    <>
      ...
    </>
  )
}

so that we can add some logic before we return the JSX (the first form is an implicit return).

Let’s import useState from react:

import { useState } from 'react'

then we create 3 state properties, one for each element in the form:

components/RegistrationModal.js

export default props => {
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const [passwordconfirmation, setPasswordconfirmation] = useState('')

  return (
    <>
      ...
    </>
  )
}

Now to each form item, we add an onChange event listener, which uses the corresponding hook updater function to set the state value when the user types into the form fields:

components/RegistrationModal.js

import { useState } from 'react'

export default props => {
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const [passwordconfirmation, setPasswordconfirmation] = useState('')

  return (
    <>
      <h2>Sign up</h2>
      <div>
        <form
          onSubmit={event => {
            alert('Sign up!')
            event.preventDefault()
          }}>
          <input
            id='email'
            type='email'
            placeholder='Email address'
            onChange={event => setEmail(event.target.value)}
          />
          <input
            id='password'
            type='password'
            placeholder='Password'
            onChange={event => setPassword(event.target.value)}
          />
          <input
            id='passwordconfirmation'
            type='password'
            placeholder='Enter password again'
            onChange={event => setPasswordconfirmation(event.target.value)}
          />
          <button>Sign up</button>
        </form>
        <p>
          Already have an account?{' '}
          <a href='#' onClick={() => props.showLogin()}>
            Log in
          </a>
        </p>
      </div>
    </>
  )
}

Great! When the form is submitted, now, we can console.log the values of the state to make sure they are updated, as we expect:

components/RegistrationModal.js

<form
  onSubmit={event => {
    console.log(email, password, passwordconfirmation)
    event.preventDefault()
  }}>

If you try to sign up using the website, you should see the values you entered printed in the browser console.

Now go to the terminal, press control-c to stop the application and run this command to install a the Axios npm package:

npm install axios

Then run npm run dev again to start the Next.js app.

Now switch back to the editor and include Axios in the RegistrationModal component:

components/RegistrationModal.js

import axios from 'axios'

and in the form onSubmit event handler function, let’s send those form values to the server, to the auth/register endpoint:

const submit = async () => {
  const response = await axios.post('/api/auth/register', { email, password, passwordconfirmation })
  console.log(response)
}

See? We use the /api/auth/register route, which directly points to the pages/api/auth/register.js file.

Unfamiliar with Axios? See my Axios tutorial

Great! Now if you try to fill the registration form and submit the data:

you’ll see the server prints “POST request received” in the terminal.

Now in the API endpoint let’s add console.log(req.body) and let’s also send a 200 response back to the client:

pages/api/auth/register.js

export default (req, res) => {
  if (req.method !== 'POST') {
    res.status(405).end() //Method Not Allowed
    return
  }
  console.log(req.body)
  res.end()
}

In the terminal, you’ll see the data coming in correctly to the server:

And in the client a successful response.

The code for this lesson is available at https://github.com/flaviocopes/airbnb-clone-react-nextjs/commit/e35781c5c404200afcc1388f4d4f31d42884e96d


Go to the next lesson