In this tutorial, we will be exploring how to implement router authentication in a Next.js app using sessions, cookies, and JSON Web Tokens (JWTs). Router authentication is essential for protecting sensitive pages or routes in your application and ensuring that only authenticated users can access them.
Here’s a step-by-step guide on how to set up router authentication in a Next.js app:
Step 1: Set up your Next.js app
Before we begin implementing router authentication, make sure you have a Next.js app set up and running. If you haven’t already created a Next.js app, you can do so by running the following command:
npx create-next-app your-app-name
Next, navigate to your app directory and start the development server by running:
npm run dev
Step 2: Install necessary packages
To implement router authentication, we’ll need to install a few packages. Run the following command to install dependencies:
npm install next-cookies cookie jwt-decode
Step 3: Create a custom hook for authentication
Next, we’ll create a custom hook that will handle authentication logic in our app. Create a new file called useAuth.js
in your hooks
directory and add the following code:
import { useState, useEffect } from 'react';
import cookies from 'next-cookies';
import jwtDecode from 'jwt-decode';
const useAuth = () => {
const [user, setUser] = useState(null);
useEffect(() => {
const token = cookies.get(null).token;
if (token) {
const decodedToken = jwtDecode(token);
setUser(decodedToken);
} else {
setUser(null);
}
}, []);
const login = (token) => {
cookies.set(null, 'token', token, { path: '/' });
const decodedToken = jwtDecode(token);
setUser(decodedToken);
};
const logout = () => {
cookies.remove(null, 'token');
setUser(null);
};
return { user, login, logout };
};
export default useAuth;
This custom hook will handle setting and removing the JWT token in cookies, as well as decoding the token to get user information. It will also provide login and logout functions.
Step 4: Protect routes with authentication
Now let’s protect the routes in our app with authentication. To do this, we’ll create a higher-order component (HOC) called withAuth
that will check if the user is authenticated before rendering the page. Create a new file called withAuth.js
in your hoc
directory and add the following code:
import { useRouter } from 'next/router';
import useAuth from '../hooks/useAuth';
const withAuth = (Component) => {
const Auth = (props) => {
const { user } = useAuth();
const router = useRouter();
if (!user) {
router.push('/login');
return null;
}
return <Component {...props} />;
};
return Auth;
};
export default withAuth;
Step 5: Implement login and logout functionality
To enable users to log in and out of your app, create a new login page and implement login and logout functionality. Create a new page called login.js
in your pages
directory with the following code:
import { useState } from 'react';
import { useRouter } from 'next/router';
import useAuth from '../hooks/useAuth';
const Login = () => {
const { login } = useAuth();
const router = useRouter();
const [credentials, setCredentials] = useState({ username: '', password: '' });
const handleSubmit = (e) => {
e.preventDefault();
// Perform authentication logic here
login('your_jwt_token_here');
router.push('/');
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={credentials.username}
onChange={(e) => setCredentials({ ...credentials, username: e.target.value })}
/>
<input
type="password"
value={credentials.password}
onChange={(e) => setCredentials({ ...credentials, password: e.target.value })}
/>
<button type="submit">Log In</button>
</form>
);
};
export default Login;
Step 6: Protect routes using the withAuth HOC
Finally, to protect a route in your app, use the withAuth
HOC that we created earlier. For example, let’s protect a dashboard page. Create a new page called dashboard.js
in your pages
directory with the following code:
import withAuth from '../hoc/withAuth';
const Dashboard = () => {
return (
<div>
<h1>Dashboard</h1>
</div>
);
};
export default withAuth(Dashboard);
Now, the Dashboard
page will only be accessible to authenticated users. If a user is not authenticated, they will be redirected to the login page to log in.
Congratulations! You have successfully implemented router authentication in your Next.js app using sessions, cookies, and JWTs. This will help protect sensitive routes and ensure that only authenticated users can access them. Feel free to customize the authentication logic and user experience to fit your app’s requirements.
which nextjs version is this? which version should I take for a new project?
would be great if there is an example with service worker.
Why is email 'null'? Shouldn't the email that was typed in be displayed under the form?
Thanks! for the tutorial, just a small note for those that wonder why the email value is always null, simply add name='email' to the input field
The website I'm working on uses Akamai as the first cache layer to cache the HTML response. In this case, the login mechanism must be handled client-side to avoid security issues and data leaks right? Does this prevent me from managing the session server-side?
Garcia Frank Davis Jose Rodriguez Anthony
please do one on google recaptcha
This approach is more usefull than using Auth.js. I don't know why it's so popular but it's coding approach is more confusing and may be need more logic and code than this nextjs official approach.
Do you really trust jose to encrypt your jwt?
Hello, I have a genuine doubt: how can we use clean architecture on Next?
I know this is a very big long shot, but I would absolutely love to see a video about a multi-tenant nextjs app with authentication (with custom domains and such). Ideally without using the Vercel starter kit, cuz that's no way to learn how it actually works… Also not ideal for people not hosting on Vercel. As far as I can tell there is not a single good resource for this on either YouTube or Google.
This was great. Thank you
Hi, I'm having a problem using authjs, when the admin deletes the user from the admin dashboard or database, then the user who is deleted should be logged out and their session cookie should be deleted but nextauth is not following that behaviour or maybe I'm not setting things up correctly, so If you have any idea about this then please let me know, and I'm using the "JWT Strategy". Thanks
awesome
I want to thank you for this excellent introduction to authentication in Next.js
Authjs is still in beta 😢
When will it be ready for production?
Thank you for a basic tutorial
No database session in nextAuth credentials strategy, hence why i prefer Lucia Auth
i got this error below when using getSession() on the middleware and other page. also the cookies is suddenly got deleted in random occassion.
although i did the exact same method with your example.
node_modulesjosedistbrowserlibjwt_claims_set.js (89:18) @ default
"exp" claim timestamp check failed
I wanted to use Zustand to have my user data and token in a client-side store, the I made my <<root template.tsx>> as server component and did the "get token and user" logic there and wrapped the zustand Provider around the children of the component, since I couldn't use layout.tsx because it didn't update I used template.tsx instead
is it a bad practice? what should I do?
I am using Laravel as my backend service
please answer I need your help