I am trying to integrate authentication with next-auth
library in an Application. I have been following the official tutorial given here https://github.com/nextauthjs/next-auth-example/. The problem with the given example is that I need to check if there is a session on every page that requires authentication like this.
import { useState, useEffect } from 'react';
import { useSession } from 'next-auth/client'
export default function Page () {
const [ session, loading ] = useSession()
// Fetch content from protected route
useEffect(()=>{
const fetchData = async () => {
const res = await fetch('/api/examples/protected')
const json = await res.json()
}
fetchData()
},[session])
// When rendering client side don't display anything until loading is complete
if (typeof window !== 'undefined' && loading) return null
// If no session exists, display access denied message
if (!session) { return <Layout><AccessDenied/></Layout> }
// If session exists, display content
return (
<Layout>
<h1>Protected Page</h1>
<p><strong>{content || "\u00a0"}</strong></p>
</Layout>
)
}
or like this for Server-side checking
import { useSession, getSession } from 'next-auth/client'
import Layout from '../components/layout'
export default function Page () {
// As this page uses Server Side Rendering, the `session` will be already
// populated on render without needing to go through a loading stage.
// This is possible because of the shared context configured in `_app.js` that
// is used by `useSession()`.
const [ session, loading ] = useSession()
return (
<Layout>
<h1>Server Side Rendering</h1>
<p>
This page uses the universal <strong>getSession()</strong> method in <strong>getServerSideProps()</strong>.
</p>
<p>
Using <strong>getSession()</strong> in <strong>getServerSideProps()</strong> is the recommended approach if you need to
support Server Side Rendering with authentication.
</p>
<p>
The advantage of Server Side Rendering is this page does not require client side JavaScript.
</p>
<p>
The disadvantage of Server Side Rendering is that this page is slower to render.
</p>
</Layout>
)
}
// Export the `session` prop to use sessions with Server Side Rendering
export async function getServerSideProps(context) {
return {
props: {
session: await getSession(context)
}
}
}
This is a lot of headaches as we need to manually right on every page that requires auth, Is there any way to globally check if the given route is a protected one and redirect if not logged in instead of writing this on every page?
you can make the authentication of user on server-side, if a user is logged in then show them the content of the protected route else redirect them to some other route.
NextAuth. js is designed as a secure, confidential client and implements a server side authentication flow.
Yes you need to check on every page and your logic is okay ( showing spinner untll the auth state is available) however,you can lift authentication state up, so you don't repeat the auth
code for every page,
_app
component is a perfect place for this, since it naturally wraps all other components (pages).
<AuthProvider>
{/* if requireAuth property is present - protect the page */}
{Component.requireAuth ? (
<AuthGuard>
<Component {...pageProps} />
</AuthGuard>
) : (
// public page
<Component {...pageProps} />
)}
</AuthProvider>
AuthProvider
component wraps logic for setting up third party providers (Firebase, AWS Cognito, Next-Auth)
AuthGuard
is the component where you put your auth check logic. You will notice that AuthGuard
is wrapping the Component
(which is the actual page in Next.js framework). So AuthGuard
will show the loading indicator while querying the auth provider, and if auth is true it will show the Component
if auth is false, it could show a login popup or redirect to the login page.
About Component.requireAuth
this is a handy property that is set on every page to mark the Component
as requiring auth, if that prop is false AuthGuard
is never rendered.
I've written about this pattern in more detail: Protecting static pages in Next.js application
And I've also made an example demo app (source)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With