Den Dribbles

Authentication with Next Auth

June 24, 2020

In this example, we are going to use “Next Auth” to do some basic authentication from their example and set up a MySQL DB in a local development Docker container to store the session and user information.

The prerequisites are that you have Docker and the use Nodejs suspects installed.

Understanding some basics behind Docker and MySQL is recommended, but not essential to get to the end (famous last words).

Setting up MySQL with Docker

docker pull mysql/mysql-server
docker run --name sql-test -e MYSQL_ROOT_PASSWORD=password -p 6000:3306 -d mysql/mysql-server:latest
# confirm container running
docker ps

You should see something like the following:

CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS                            PORTS                               NAMES
30be83a35610        mysql/mysql-server:latest   "/entrypoint.sh mysq…"   6 seconds ago       Up 2 seconds (health: starting)   33060/tcp, 0.0.0.0:6000->3306/tcp   sql-test

Note that anything store in the container will be lost without persisting the data. For development purposes, this is okay by us.

We have the server port forwarding from 3306 on the container to 6000 for us to access on localhost.

# where 30be83a35610 is there CONTAINER ID
docker exec 30be83a35610 -it /bin/bash

This will take you into the Docker container shell, where we can login into MySQL.

mysql -u root -p
# enter "password" when prompted

You can go straight into mysql from the docker exec, but I thought going the long way might be more fun for those playing around with containers.

Now we can create a database to use for this example.

create database next_auth;
show databases;
-- you should now be able to see "next_auth"

In order to get things going, you may need to make some changes. I had to do the following.

UPDATE mysql.user SET Host='%' WHERE Host='localhost' AND User='root';
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
FLUSH PRIVILEGES;

Note: Using the root isn’t a great idea, but this is simply for demonstration purposes and to get things up and running.

For here, you can exit the MySQL shell and run exit it again to leave the Docker container.

Setting up Next.js

We are going to use a basic setup using create-next-app and make some adjustments from there.

npx create-next-app

Fill out the defaults for it to move onto the next part of installing some extra packages.

yarn add next-auth mysql dotenv

We are using “dotenv” for loading a local .env file for local development.

Here, we are just going to use GitHub OAuth for logging in.

Setting up Next Auth in the application

Create a file pages/api/auth/[...nextauth].js.

Add the following:

import NextAuth from "next-auth"
import Providers from "next-auth/providers"

require("dotenv").config()

const options = {
  site: process.env.SITE || "http://localhost:3000",

  // Configure one or more authentication providers
  providers: [
    Providers.GitHub({
      clientId: process.env.GITHUB_ID,
      clientSecret: process.env.GITHUB_SECRET,
    }),
  ],

  // A database is optional, but required to persist accounts in a database
  database: process.env.DATABASE_URL,
}

export default (req, res) => NextAuth(req, res, options)

Then we will update the pages/index.js to show a basic login format taken from the Next Auth example:

import React from "react"
import { useSession } from "next-auth/client"

export default () => {
  const [session, loading] = useSession()

  return (
    <p>
      {!session && (
        <>
          Not signed in <br />
          <a href="/api/auth/signin">Sign in</a>
        </>
      )}
      {session && (
        <>
          Signed in as {session.user.email} <br />
          <a href="/api/auth/signout">Sign out</a>
        </>
      )}
    </p>
  )
}

That is all we need to do for the application! We won’t start running anything just yet… there are a couple of things we want to get setup first.

Setting up ngrok

We are using tunneling to forward our localhost address out to the big, bad world.

If you haven’t got ngrok installed, visit the website for setup instructions. If you use Brew, you can use brew cask install ngrok.

ngrok http 3000 # will forward 3000 out

Once you run that, you will get an address to use.

Alternatively, you may use PageKite as another tunneling service.

Here a look at my editor once ngrok was up and running in the terminal:

ngrok

Setting up GitHub OAuth

Follow the guide on how to set up a GitHub OAuth Application

We will need to grab both the ID and the token given back.

Note: For the authentication callback, you will need to keep the format {server}/api/auth/callback/{provider}. This will be the ngrok server address.

This is a look at how my setup was for this particular example:

GitHub OAuth App

Env Variables

We are now at a place where we need to create our .env file and add the credentials and address that we got from before:

GITHUB_ID=<from-github>
GITHUB_SECRET=<from-github>
# The MySQL database being forwarded from Docker,
# where 'next_auth' is the database we created
DATABASE_URL="mysql://root:password@127.0.0.1:6000/next_auth?synchronize=true"
SITE=<ngrok-server>

For the DATABASE_URL, note that we are running on port 6000 as we are forwarding from 3306 on the Docker container to 6000. This ensures you won’t clash with any local MySQL application you may have running on your local machine. The next_auth is the name of the database we creating in the initial steps.

Running Dev

Now is the fun part.

yarn dev

If we head to http://localhost:3000, we will see the application, however we want to head to the ngrok address instead in our case.

Homepage

If we click on sign in, we’ll be taken to a default setup page for logging in with GitHub.

Login

Clicking this will take you through a familiar flow for signing into an OAuth app with GitHub.

GitHub App acceptance

Finally, once the callback runs its normal phase, we will arrive back home.

Post-auth

Notice now that we are now signed in! Hooray!

Checking out what changed in MySQL

Given that we opted to use a database to store sessions, we could now attach to the Docker container once again and jump into MySQL.

Once back into the MySQL shell, run the following:

USE next_auth;
SHOW tables;
SELECT * FROM sessions;
SELECT * FROM users;

Here we can see our info has come across! Easy peasy!

MySQL DB

This has been a real barebones look at working with MySQL within a Docker container and running a Nextjs app with Next Auth, but there are a bunch of really next OAuth and database options they support - each essentially a similar approach as the above! Jump onto their docs and play around.

Resources and Further Reading

  1. Next.js - Getting Started
  2. Next Auth
  3. Set up a GitHub OAuth Application
  4. Ngrok
  5. Ngrok alternative - PageKite
  6. Docker - mysql/mysql-server

A personal blog on all things of interest. Written by Dennis O'Keeffe, Follow me on Twitter