NextAuth.js Intro [2 of 3]: Magic Link Email Authentication
Tags: nextjs, jamstack, react, javascript
Published: 2021-05-20 17:27:07

---
title: NextAuth.js Intro [2 of 3]: Magic Link Email Authentication 
published: true
description: An intro to the next-auth library which makes full-stack authentication in Next.js dead simple.
tags: nextjs,jamstack,reactjs,javascript
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hqnohqkiflkheu7zfelk.png
series: next-auth-example
---

![NextAuth.js logo](https://cdn-images-1.medium.com/max/1024/0*wjf8TBRVNbjLazqI.png)


From my previous article in this series, we know that one-click signup / sign in with next-auth using Google, GitHub, Facebook, or any other provider is pretty easy. Another way many apps like to allow people to sign in easily is via use of a “magic link.” The user will enter their email address and receive an email with a link they can click to login to the app.

As you may have guessed, that’s pretty easy with next-auth too 😉 Here’s how to do it.

### Links

* Source code on [GitHub](https://github.com/echobind/next-auth-example/tree/with-email-auth)

### Shameless Plug

I teach you to use NextAuth.js along with Prisma, Stripe, Chakra-UI, React Hook Form, Vercel and Railway to build a SaaS app in my book, [Cut Into The Jamstack](https://www.cutintothejamstack.com/). 



### Create and structure a database

Database integration is required for email auth in next-auth currently, so we need to get this running first.

First we need a database. PostgresSQL is our default relational DB choice at [Echobind](https://echobind.com/), so that’s what we’ll use for this example. I use [Postgres.app](https://postgresapp.com/) for Postgres on localhost, and often start with a Heroku Postgres DB on the Hobby plan for the deployed version of small projects like this.

Connect to your database using psql or a client like [Postico](https://eggerapps.at/postico/).

First create a database:

```sql
CREATE DATABASE "next-auth-example"
```

The database needs some structure to hold user information in it, which next-auth [provides on their website](https://next-auth.js.org/schemas/postgres). Run these CREATE TABLE statements and that'll do the trick.

```sql
CREATE TABLE accounts  
 (  
 id SERIAL,  
 compound_id VARCHAR(255) NOT NULL,  
 user_id INTEGER NOT NULL,  
 provider_type VARCHAR(255) NOT NULL,  
 provider_id VARCHAR(255) NOT NULL,  
 provider_account_id VARCHAR(255) NOT NULL,  
 refresh_token TEXT,  
 access_token TEXT,  
 access_token_expires TIMESTAMPTZ,  
 created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,  
 updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,  
 PRIMARY KEY (id)  
 );

CREATE TABLE sessions  
 (  
 id SERIAL,  
 user_id INTEGER NOT NULL,  
 expires TIMESTAMPTZ NOT NULL,  
 session_token VARCHAR(255) NOT NULL,  
 access_token VARCHAR(255) NOT NULL,  
 created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,  
 updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,  
 PRIMARY KEY (id)  
 );

CREATE TABLE users  
 (  
 id SERIAL,  
 name VARCHAR(255),  
 email VARCHAR(255),  
 email_verified TIMESTAMPTZ,  
 image TEXT,  
 created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,  
 updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,  
 PRIMARY KEY (id)  
 );

CREATE TABLE verification_requests  
 (  
 id SERIAL,  
 identifier VARCHAR(255) NOT NULL,  
 token VARCHAR(255) NOT NULL,  
 expires TIMESTAMPTZ NOT NULL,  
 created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,  
 updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,  
 PRIMARY KEY (id)  
 );

CREATE UNIQUE INDEX compound_id  
 ON accounts(compound_id);

CREATE INDEX provider_account_id  
 ON accounts(provider_account_id);

CREATE INDEX provider_id  
 ON accounts(provider_id);

CREATE INDEX user_id  
 ON accounts(user_id);

CREATE UNIQUE INDEX session_token  
 ON sessions(session_token);

CREATE UNIQUE INDEX access_token  
 ON sessions(access_token);

CREATE UNIQUE INDEX email  
 ON users(email);

CREATE UNIQUE INDEX token  
 ON verification_requests(token);
```

Your database will now look like this (screenshot from Postico):

### Connect database and enable email provider in next-auth

Next we need to add the database adapter to our repo.

`yarn add pg`

or `npm install --save pg`

Add the connection string to your `.env` file, so next-auth knows where to look for it.

```shell
DATABASE_URL="postgres://my-root-user:my-root-pass@localhost:5432/next-auth-example?schema=public"
```

Then uncomment this line in `pages/api/auth/[...nextauth].js` so that next-auth knows where the database is:

```javascript
database: process.env.DATABASE_URL,
```

Now we tell next-auth that we want to use email for authentication in that same file. In the array of providers, add:

```javascript
Providers.Email({  
 server: process.env.EMAIL_SERVER,  
 from: process.env.EMAIL_FROM,  
}),
```

### Set default theme

In next-auth 3.2, you’re able to set your sign in pages to use a light or dark theme, or to use the system theme (which is the default). The only quirk with this is that if your system is set to a dark theme, the background of the sign in page will be dark but so will the text, rendering it invisible!

As an easy remedy, I set the theme to light . in `pages/api/auth/[...nextauth].js` :

```javascript
const options = {  
 theme: 'light',  
 // ... other options  
};
```

### Connect an email provider

Create an account with an email service so that your app can send emails out transactionally. My default is usually [SendGrid](http://sendgrid.io/), but there are tons of others. With any provider you’ll have to create an account, verify an email address to send from, and get the SMTP credentials from your account.

Once you have those credentials, you can add them to your `.env` file. My SendGrid configuration looks like this:

```shell
EMAIL_SERVER=smtp://apikey:BIG-LONG_CRYPTIC_STRING:587  
EMAIL_FROM=your-verified-sending-email@yourdomain.com
```

There are different ways you can specify this configuration as well, see the [docs](https://next-auth.js.org/providers/email#configuration).

### Restart and test

Restart your local server for the settings to take effect, visit your sign in screen and log in with an email. You should get an email like the below:

That’ll take you to the landing page, now signed in 🎉

One thing to note is that when logging in with email, we don’t have any other information about the user automatically, so their name in the screenshot above is blank since it doesn’t exist. A small conditional will change that.

In `pages/index.js` we just update our conditional:

```javascript
{session && session.user && session.user.name && (  
 <h3>Logged in as {session.user.name}</h3>  
)}
```

And now the text makes a lot more sense.

So far we’ve got two methods for logging in fast, and easily in Next.js using next-auth. Later in this series we'll explore what you can do with user information now that the user is logged in.


---

This article was [originally published](https://blog.echobind.com/magic-link-email-authentication-in-next-js-with-next-auth-and-postgresql-bf12b4fa908a) on [the Echobind Blog](https://blog.echobind.com).