User Authentication in Next.js with Strapi

Introduction

Software Required to Run the Application

  1. Docker (Click here to download.)
  2. npm (Click here to download.)
  3. yarn (Click here to download.)

Creating a New Next.js Application

yarn create next-app
cd frontend && yarn dev

Creating a New Strapi Application

# backend/docker-compose.ymlversion: '3'
services:
strapi:
container_name: strapi
image: strapi/strapi
environment:
- DATABASE_CLIENT=postgres
- DATABASE_HOST=db
- DATABASE_PORT=5432
- DATABASE_NAME=strapi
- DATABASE_USERNAME=strapi
- DATABASE_PASSWORD=strapi
ports:
- 1337:1337
volumes:
- ./app:/srv/app
depends_on:
- db
db:
container_name: postgres
image: postgres
restart: always
volumes:
- ./db:/var/lib/postgresql/data
ports:
- 5432:5432
environment:
POSTGRES_USER: strapi
POSTGRES_PASSWORD: strapi
POSTGRES_DB: strapi
docker-compose up
  • When running this image, Strapi will check if there is a project in the /srv/app folder of the container. If there is nothing, it will run the Strapi new command in the container /srv/app folder.

Creating and Integrating Google OAuth Client into our Applications

  1. Create a new OAuth client ID.
  2. Choose “web application” as the application type.
  3. Add the following authorized redirect URLs:
// frontend/.envNEXT_PUBLIC_API_URL=http://localhost:1337
NEXT_PUBLIC_DATABASE_URL=postgres://strapi:strapi@localhost:5432/strapi?synchronize=true
NEXTAUTH_URL=http://localhost:3000
GOOGLE_CLIENT_ID="12345.apps.googleusercontent.com"
GOOGLE_CLIENT_SECRET="1234-567-9"

Installing and Integrating NextAuth with Next.js and Strapi

yarn add next-auth
// frontend/pages/api/auth/[...nextauth].jsimport NextAuth from "next-auth";
import Providers from "next-auth/providers";

const options = {
providers: [
Providers.Google({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
}),
],
database: process.env.NEXT_PUBLIC_DATABASE_URL,
session: {
jwt: true,
},
callbacks: {
session: async (session, user) => {
session.jwt = user.jwt;
session.id = user.id;
return Promise.resolve(session);
},
jwt: async (token, user, account) => {
const isSignIn = user ? true : false;
if (isSignIn) {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/auth/${account.provider}/callback?access_token=${account?.accessToken}`
);
const data = await response.json();
token.jwt = data.jwt;
token.id = data.user.id;
}
return Promise.resolve(token);
},
},
};

const Auth = (req, res) =>
NextAuth(req, res, options);

export default Auth;
// frontend/pages/index.jsimport { getSession, signIn, signOut } from "next-auth/client";
import Head from 'next/head';
import Link from "next/link";
import React from "react";

const IndexPage = ({
session,
}) => {
const signInButtonNode = () => {
if (session) {
return false;
}

return (
<div>
<Link href="/api/auth/signin">
<button
onClick={(e) => {
e.preventDefault();
signIn();
}}
>
Sign In
</button>
</Link>
</div>
);
};

const signOutButtonNode = () => {
if (!session) {
return false;
}

return (
<div>
<Link href="/api/auth/signout">
<button
onClick={(e) => {
e.preventDefault();
signOut();
}}
>
Sign Out
</button>
</Link>
</div>
);
};

if (!session) {
return (
<div className="hero">
<div className="navbar">
{signOutButtonNode()}
{signInButtonNode()}
</div>
<div className="text">
You aren't authorized to view this page
</div>
</div>
)
}

return (
<div className="hero">
<Head>
<title>Index Page</title>
</Head>
<div className="navbar">
{signOutButtonNode()}
{signInButtonNode()}
</div>
<div className="text">
Hello world
</div>
</div>
);
};

export const getServerSideProps = async ({ req }) => {
const session = await getSession({ req });
return {
props: {
session,
},
};
};

export default IndexPage;

Conclusion

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Strapi

Strapi

2.1K Followers

The open source Headless CMS Front-End Developers love.