Private page

Private Pages

Veloz provides some set of utilities function mean't to protect routes either server or client from getting access. This utilities function / components can be found in src/lib/auth-helpers folder.

Client 🖥

withAuth

withAuth is a higher order component that can be used to protect client side routes from getting access. It takes a component as an argument and returns a new and modified component that can be used to protect routes.

When a user isn't authenticated, the component will redirect the user to the login page. If the user is authenticated, the component will render the passed in component.

💡

Only use this HOC (High Order Component) to protect pages / components that are mean't to be accessed by authenticated users only.

withAuth.tsx
withAuth.tsx

_12
import { FullPageLoader } from "@/components/Loader";
_12
import { DataContext } from "@/context/DataContext";
_12
import useAuthUser from "@/hooks/useAuthUser";
_12
import { useSession } from "next-auth/react";
_12
import React, { useCallback, useContext, useEffect } from "react";
_12
_12
export default function withAuth<P extends { children: React.ReactNode }>(
_12
Component: React.ComponentType<P>
_12
) {
_12
const ComponentWithAuth = (props: P) => {...};
_12
return ComponentWithAuth;
_12
}

withoutAuth

As the name implies withoutAuth the opposite of withAuth. It is used to protect client side routes from getting access. It takes a component as an argument and returns a new and modified component that can be used to protect routes.

When a user is authenticated, the component will redirect the user to the dashboard page. If the user isn't authenticated, the component will render the passed in component.

💡

Only use this HOC (High Order Component) to protect pages / components that are mean't to be accessed by unauthenticated users only. for eg authentication route / page

withoutAuth.tsx
withoutAuth.tsx

_10
import { FullPageLoader } from "@/components/Loader";
_10
import { useSession } from "next-auth/react";
_10
import React, { useEffect } from "react";
_10
_10
export function withoutAuth<P extends { children: React.ReactNode }>(
_10
Component: React.ComponentType<P>
_10
) {
_10
const ComponentWithAuth = (props: P) => {...};
_10
return ComponentWithAuth;
_10
}

Use Case

Assuming we have a page called dashboard.tsx that should only be accessible by authenticated users only. We can use withAuth to protect the page from getting access by unauthenticated users. We can also use withoutAuth to protect a page that should only be accessible by unauthenticated users only.

dashboard.(tsx
auth.(tsx

_11
import { withAuth } from "@/lib/auth-helpers";
_11
_11
function Dashboard() {
_11
return (
_11
<div>
_11
<h1>Dashboard Page</h1>
_11
</div>
_11
);
_11
}
_11
_11
export default withAuth(Dashboard);

Server ☁️

Protecting API routes / endpoints is quite handled differently from that of client side pages / routes. Endpoints are protected using isAuthenticated middleware HOF (High Order Function) and can be found in /src/app/api/middlewares/auth.(ts) file.

isAuthenticated

auth.ts
auth.js

_34
export function isAuthenticated(fn: Function) {
_34
return async (req: NextApiRequest) => {
_34
const session = await getServerSession(nextAuthOptions);
_34
if (!session) {
_34
throw new HttpException(RESPONSE_CODE.UNAUTHORIZED, "Unauthorized", 401);
_34
}
_34
_34
let user = null;
_34
_34
// oauth provider like github sometimes dont include email
_34
if (session.user.email) {
_34
user = await prisma.users.findFirst({
_34
where: { email: session.user?.email as string },
_34
});
_34
} else {
_34
user = await prisma.users.findFirst({
_34
where: { uId: session.user?.id as string },
_34
});
_34
}
_34
_34
if (!user) {
_34
throw new HttpException(
_34
RESPONSE_CODE.UNAUTHORIZED,
_34
`Unauthorized, Invalid Token`,
_34
403
_34
);
_34
}
_34
_34
(req as any)["user"] = { id: user.uId };
_34
return await fn(req);
_34
_34
}
_34
_34
};

Use Case

Simply wrap your API route handler with isAuthenticated() middleware to protect it from getting access by unauthenticated users.

user/route.ts

_10
import { NextRequest } from "next/server";
_10
import { isAuthenticated } from "../middlewares/auth";
_10
import CatchError from "../utils/_error";
_10
import UserController from "../controllers/user.controller";
_10
_10
const userController = new UserController();
_10
_10
export const GET = CatchError(
_10
isAuthenticated(async (req: NextRequest) => await userController.getUser(req))
_10
);

Each time a request is made to the server for that specific endpoint and the user making the requests isn't authenticated, the server simply throw an error with status code 401 and message Unauthorized.

More details about Error Handling, please checkout this 👉 section.

© Veloz 2024