Skip to main content

๐Ÿ” Protecting Your Next.js App: Redirecting Unauthorized Users to the Login Page with Middleware

Introduction

When building an app with Next.js, ensuring that only authenticated users access certain pages is crucial for protecting sensitive data. One effective way to do this is by implementing a global authentication check with middleware. This approach lets you automatically redirect unauthorized users to the login page without needing to repeat checks across multiple pages. In this article, I’ll walk you through setting up a global authentication check using Next.js middleware and share some useful client-side tricks for extra protection.

Why Use Middleware for Authentication in Next.js?

Next.js middleware is a powerful tool that can intercept and process requests before they reach the route handlers. By implementing middleware, you can:

  • Centralize Authentication Logic: No need to handle authentication on each page.
  • Protect Multiple Pages Efficiently: Easily redirect unauthorized users across many routes.
  • Improve Code Readability and Maintenance: Keeping authentication in one place reduces clutter on your pages.

Step 1: Setting Up Middleware to Check for Authentication

Start by creating a middleware.ts file in your Next.js project’s root directory. This file will hold the logic that checks whether a user is authenticated and redirects them to the login page if they aren’t.

Here’s the code to create your authentication middleware:

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
// Check if the request includes an authentication token
const token = request.cookies.get('access-token');
// If no token is found, redirect to the login page
if (!token) {
const loginUrl = request.nextUrl.clone();
loginUrl.pathname = '/login';
return NextResponse.redirect(loginUrl);
}
// Allow access if token exists
return NextResponse.next();
}
// Define the routes that should trigger this middleware
export const config = {
matcher: '/((?!api|_next/static|_next/image|favicon.ico|login).*)',
};

Here’s how this works:

  • The middleware reads the access-token cookie from the request to check if the user is authenticated.
  • If the access-token cookie is missing, it redirects the user to the /login page.
  • The matcher configuration ensures that the middleware applies to all pages except the API routes, static assets, and the /login page itself.

Step 2: Adding Client-Side Protection (Optional)

While middleware handles authentication checks at the server level, it can be useful to add a client-side check as well. For example, if a user loses their session while navigating, a client-side check can help catch this and redirect them.

Below is an example of adding a client-side check in a component that requires authentication. This can act as a backup to ensure the user is redirected if they are not logged in.

import React, { useEffect } from 'react';
import { useRouter } from 'next/router';

export default function ProtectedPage() {
const router = useRouter();
useEffect(() => {
const accessToken = document.cookie.includes('access-token');
// Redirect to login if no access token is found
if (!accessToken) {
router.push('/login');
}
}, [router]);
return (
<div>
<h1>Welcome to the Protected Page!</h1>
{/* Protected content goes here */}
</div>

);
}

Step 3: Testing Your Authentication Middleware

To ensure everything is working, try accessing a protected route without being logged in. You should be redirected to the login page as expected. Once you log in and obtain an access-token cookie, try accessing the protected routes again—you should now be allowed access!

Step 4: Additional Server-Side Check with getServerSideProps (Optional)

If you’re using server-side rendering on a particular page and need to verify user authentication, you can add a getServerSideProps function that checks for the token on the server side and redirects if necessary.

Here’s how this might look in a protected page with getServerSideProps:

import { GetServerSideProps } from 'next';

export const getServerSideProps: GetServerSideProps = async (context) => {
const { req } = context;
// Check if access-token exists in cookies
const token = req.cookies['access-token'];
if (!token) {
return {
redirect: {
destination: '/login',
permanent: false,
},
};
}
return {
props: {}, // Pass any necessary props to the page component
};
};
export default function ProtectedPage() {
return <div>Protected content for authenticated users</div>;
}

This server-side check is a useful fallback, especially for pages that need to retrieve server-rendered data.

Wrapping Up

By setting up middleware in Next.js, you can streamline your authentication checks and protect all your app’s pages efficiently. This approach keeps your code clean and ensures that users are always redirected to the login page if they aren’t authorized.

With these steps, you’re now set to keep your Next.js app secure and your code organized! ๐ŸŽ‰

    Popular posts from this blog

    Xcode and iOS Version Mismatch: Troubleshooting "Incompatible Build Number" Errors

    Have you ever encountered a frustrating error while trying to run your iOS app in Xcode, leaving you scratching your head? A common issue arises when your device's iOS version is too new for the Xcode version you're using. This often manifests as an "incompatible build number" error, and looks like this: DVTDeviceOperation: Encountered a build number "" that is incompatible with DVTBuildVersion. This usually happens when you are testing with beta versions of either iOS or Xcode, and can prevent Xcode from properly compiling your storyboards. Let's explore why this occurs and what you can do to resolve it. Why This Error Occurs The core problem lies in the mismatch between the iOS version on your test device and the Software Development Kit (SDK) supported by your Xcode installation. Xcode uses the SDK to understand how to build and run apps for specific iOS versions. When your device runs a newer iOS version than Xcode anticipates, Xcode mi...

    How to Fix the “Invariant Violation: TurboModuleRegistry.getEnforcing(…): ‘RNCWebView’ Could Not Be Found” Error in React Native

    When working with React Native, especially when integrating additional libraries like react-native-signature-canvas , encountering errors can be frustrating. One such error is: Invariant Violation: TurboModuleRegistry. getEnforcing (...): 'RNCWebView' could not be found This error often occurs when the necessary dependencies for a module are not properly linked or when the environment you’re using doesn’t support the required native modules. Here’s a breakdown of how I encountered and resolved this issue. The Problem I was working on a React Native project where I needed to add the react-native-signature-canvas library to capture user signatures. The installation process seemed straightforward: Installed the package: npm install react-native-signature- canvas 2. Since react-native-signature-canvas depends on react-native-webview , I also installed the WebView package: npm install react- native -webview 3. I navigated to the iOS directory and ran: cd ios pod install Everythi...

    Fixing FirebaseMessagingError: Requested entity was not found.

    If you’re working with Firebase Cloud Messaging (FCM) and encounter the error: FirebaseMessagingError: Requested entity was not found. with the error code: messaging/registration-token-not-registered this means that the FCM registration token is invalid, expired, or unregistered . This issue can prevent push notifications from being delivered to users. ๐Ÿ” Possible Causes & Solutions 1️⃣ Invalid or Expired FCM Token FCM tokens are not permanent and may expire over time. If you’re storing tokens in your database, some might be outdated. ✅ Solution: Remove invalid tokens from your database when sending push notifications. Refresh and store the latest FCM token when the app starts. Example: Automatically Refresh Token firebase. messaging (). onTokenRefresh ( ( newToken ) => { // Send newToken to your backend and update the stored token }); 2️⃣ Token Unregistered on Client Device A token might become unregistered if: The app is uninstalled on the user’s device. ...