Introduction
Strapi is a backend system provides basic crud operations with customizable content types, and auto-magically provide its Rest APIs. Next.js is an excellent framework over React.js which uses capability of React.js and provides SEO benefits by rendering pages at server side.
In this post, I will authenticate a registered user fron next.js to strapi and use its Rest API with jwt for further authenticated operations.
What We Will Learn
- Render a pre-built login form, and its corresponding actions
- authentication will be with strapi email/password system.
- Signout functionality
- Save
jwtin session - Use jwt tokens in rest-apis for authenticated calls
Pre-requisites
- Have a registered and active user in strapi.
- Have a content type.
- This content type is only usable by authenticated users.
NPM Libraries required
- axios
- next
- next-auth
- react
- react-dom
Using Next-auth
Create a file named /pages/api/auth/[...nextauth].js
import NextAuth from 'next-auth'
import Providers from 'next-auth/providers'
import axios from 'axios'
const options = {
providers: [
Providers.Credentials({
name: 'Credentials',
credentials: {
email: { label: "Email", type: "text", placeholder: "[email protected]" },
password: { label: "Password", type: "password" }
},
async authorize(credentials) {
try {
const { data } = await axios.post(`${process.env.NEXT_PUBLIC_API_URL}/auth/local`, {
identifier: credentials.email,
password: credentials.password
});
if (data) {
return data;
}
else {
return null;
}
} catch (e) {
// console.log('caught error');
// const errorMessage = e.response.data.message
// Redirecting to the login page with error message in the URL
// throw new Error(errorMessage + '&email=' + credentials.email)
return null;
}
}
})
],
session: {
jwt: true,
},
callbacks: {
// Getting the JWT token from API response
jwt: async (token, user, account) => {
const isSignIn = user ? true : false;
if (isSignIn) {
token.jwt = user.jwt;
token.id = user.user.id;
token.name = user.user.username;
token.email = user.user.email;
}
return Promise.resolve(token);
},
session: async (session, user) => {
session.jwt = user.jwt;
session.id = user.id;
return Promise.resolve(session);
},
}
}
export default (req, res) => NextAuth(req, res, options)Edit _app.js
import { Provider } from 'next-auth/client'
function MyApp({ Component, pageProps }) {
return (
<Provider session={pageProps.session}>
<Component {...pageProps} />
</Provider>
);
}
export default MyApp.env.local Environment variable file
NEXTAUTH_URL=http://localhost:3000
NEXT_PUBLIC_API_URL=http://localhost:1337Summary so far
We have configured our Next.js frontend so that we will be able to:
- Configured a credential provider in next-auth with strapi backend.
- Configured action to be performed when user submit Login form.
- Authentication rest call to strapi backend and upon successful authentication, save jwt token to session
- Easily identify if a user has logged-in or not.
- Easily get jwt token, if user has authenticated.
Playground with Sign-in/Sign-out and Authenticated Rest call
import Head from 'next/head'
import { signIn, signOut, useSession, getSession } from 'next-auth/client'
import axios from 'axios'
export default function Home(initialData) {
const [ session, loading ] = useSession()
return (
<div className='container'>
<Head>
<title>Create Next App</title>
<link rel="icon" href="/favicon.ico" />
<link rel="stylesheet" href="/style.css"/>
</Head>
<h1>Auth Test</h1>
<div>
{!session && <>
Not signed in <br/>
<button onClick={() => signIn()}>Sign in</button>
</>}
{session && <>
Signed in as {session.user.email} <br/>
<button onClick={() => signOut()}>Sign out</button>
</>}
</div>
<h1>Content...</h1>
<div>
{initialData.journals && initialData.journals.map((each, index) => {
return(
<div key={index}>
<h3>{each.Title}</h3>
<p>{each.Journal}</p>
</div>
)
})}
</div>
</div>
)
}
export async function getServerSideProps({req}) {
let headers = {}
const session = await getSession({ req });
if (session) {
headers = {Authorization: `Bearer ${session.jwt}`};
}
let journals = [];
try {
let {data } = await axios.get(`${process.env.NEXT_PUBLIC_API_URL}/journals`, {
headers: headers,
})
journals = data;
} catch (e) {
console.log('caught error');
journals = [];
}
return {props: {journals: journals}}
}Understanding getServerSideProps
First we are checking, if a session is there. If it is, then we are fetching jwt token from session and using it to pass in a Rest call for getting a content type.
Detect User is Logged-in or not
const [ session, loading ] = useSession()
{!session && <>
Not signed in <br/>
<button onClick={() => signIn()}>Sign in</button>
</>}Also see How to use Next-auth in Client side vs Server Side
The magic methods of next-auth gives you methods to get session information. You just need to check, if session is present.
If there is no session, it gives you a signin action and when you click on this button, you will be presented with the ready-made form.













