Auth Guards

Learn how to protect your application using auth guards.

Auth guards ensure that specific sections of your application are accessible only to authenticated users. By implementing route guards, you can control user access to React Server Components, React Client Components, React Server Actions and Next.js Route Handlers.

How we did it

For Next.js we used the middleware pattern to protect route handlers. This allowed us to have a simple and consistent way to protect our routes.

For Vite we created an AuthGuard component that wraps the entire /dashboard route section. This component checks if the user is authenticated and redirects them to the login page if they are not before rendering the dashboard pages.

Protecting Route Handlers

Create a route file in your application.

import { NextResponse } from "next/server";
import { getUser } from "some-auth-lib";
 
export async function GET() {
	const user = await getUser();
 
	console.log({ user });
 
	if (!user) {
		// Handle this
	}
 
	return NextResponse.json({
		success: true,
	});
}

Navigate to the endpoint (or use fetch). The user (or null) will be displayed in the terminal console.

If the user is not authenticated, you can return a 401 status code, a message, or redirect to login page.

Protecting Server Actions

Create an action that will make use of getUser to retrieve the user.

"use server";
 
import { getUser } from "some-auth-lib";
 
export async function createTask() {
	const { data: user } = await getUser();
 
	console.log({ user });
 
	if (!user) {
		// Handle this
	}
}

Create a client page (or any component) and use the new action.

"use client";
 
import * as React from "react";
 
import { createTask } from "./create-task";
 
export default function Page() {
	return (
		<div>
			<button onClick={() => createTask()}>Create Task</button>
		</div>
	);
}

Navigate to this page and click the button. The user (or null) will be displayed in the terminal console.

If the user is not authenticated, you can return an error message back to the client.

Protect a Server Components

Create a page (without the 'use client' flag).

import * as React from "react";
import { getUser } from "some-auth-lib";
 
export default async function Page() {
	const user = await getUser();
 
	console.log({ user });
 
	if (!user) {
		// Handle this
	}
 
	return <div>Welcome!</div>;
}

Navigate to the page. The user (or null) will be displayed in the terminal console.

If the user is not authenticated, you can return a specific component or redirect the user to login page.

Protect a Client Components

Create a client page (or any component).

"use client";
 
import * as React from "react";
import { getUser } from "some-auth-lib";
 
export default function Page() {
	React.useEffect(() => {
		getUser()
			.then((user) => {
				console.log({ user });
			})
			.catch(console.error);
	}, []);
 
	return <div>Welcome!</div>;
}

Navigate to the page. The user (or null) will be displayed in the browser console once the component is mounted.

If the user is not authenticated, you can return a specific component or redirect the user to login page.