Skip to content

Commit 5943995

Browse files
committed
Implement authentication blocked pages using middleware
1 parent 74baa54 commit 5943995

File tree

4 files changed

+68
-8
lines changed

4 files changed

+68
-8
lines changed
Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
1+
"use client";
2+
13
const KEY: string = "TOKEN";
24

35
export function setToken(token: string): void {
4-
window.localStorage[KEY] = token
6+
document.cookie = `${KEY}=${token}`
57
}
68

79
export function getToken(): string {
8-
return KEY in window.localStorage ? window.localStorage[KEY] : ""
10+
const keyValue = document.cookie.split("; ").find(kv => kv.startsWith(`${KEY}=`))
11+
if (keyValue == undefined) {
12+
return "";
13+
}
14+
15+
const [_, value] = keyValue.split("=");
16+
17+
if (value == undefined) {
18+
return "";
19+
}
20+
21+
return value;
922
}
1023

1124
export function deleteToken() {
12-
if (KEY in window.localStorage) {
13-
window.localStorage.removeItem(KEY);
14-
}
25+
document.cookie = `${KEY}=`;
1526
}

apps/frontend/src/app/services/user.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
"use client";
2+
3+
import { getToken } from "./login-store";
4+
15
const USER_SERVICE_URL = process.env.NEXT_PUBLIC_USER_SERVICE_URL;
26

37
export interface User {
@@ -91,7 +95,7 @@ export const UpdateUser = async (
9195
user: UpdateUserRequestType,
9296
id: string
9397
): Promise<UpdateUserResponseType> => {
94-
const JWT_TOKEN = localStorage.getItem("TOKEN") ?? undefined;
98+
const JWT_TOKEN = getToken();
9599
const response = await fetch(
96100
`${process.env.NEXT_PUBLIC_USER_SERVICE_URL}users/${id}`,
97101
{
@@ -116,7 +120,7 @@ export const UpdateUser = async (
116120
};
117121

118122
export const ValidateUser = async (): Promise<VerifyTokenResponseType> => {
119-
const JWT_TOKEN = localStorage.getItem("TOKEN") ?? undefined;
123+
const JWT_TOKEN = getToken();
120124
const response = await fetch(
121125
`${process.env.NEXT_PUBLIC_USER_SERVICE_URL}auth/verify-token`,
122126
{

apps/frontend/src/components/Header/header.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { useRouter } from "next/navigation";
1212
import "./styles.scss";
1313
import DropdownButton from "antd/es/dropdown/dropdown-button";
1414
import { LogoutOutlined, UserOutlined } from "@ant-design/icons";
15+
import { deleteToken } from "@/app/services/login-store";
1516

1617
interface HeaderProps {
1718
selectedKey: string[] | undefined;
@@ -55,7 +56,7 @@ const Header = (props: HeaderProps): JSX.Element => {
5556
),
5657
onClick: () => {
5758
// Clear away the previously stored jwt token in localstorage
58-
localStorage.clear();
59+
deleteToken();
5960
// Redirect user to login page
6061
push("/login");
6162
},

apps/frontend/src/middleware.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { log } from 'console';
2+
import { NextURL } from 'next/dist/server/web/next-url';
3+
import { redirect } from 'next/navigation'
4+
import { type NextRequest, NextResponse } from 'next/server';
5+
import { ValidateUser } from './app/services/user';
6+
import { cookies } from 'next/headers';
7+
8+
const PUBLIC_ROUTES = ["/login", "/register"];
9+
10+
async function isValidToken(TOKEN: string): Promise<boolean> {
11+
const { status } = await fetch(
12+
`${process.env.NEXT_PUBLIC_USER_SERVICE_URL}auth/verify-token`,
13+
{
14+
method: "GET",
15+
headers: {
16+
"Content-Type": "application/json",
17+
Authorization: `Bearer ${TOKEN}`,
18+
},
19+
}
20+
);
21+
return status === 200;
22+
}
23+
24+
export default async function middleware(request: NextRequest) {
25+
const REDIRECT_TO_LOGIN = NextResponse.redirect(new NextURL("/login", request.url));
26+
const TOKEN = request.cookies.get("TOKEN");
27+
if (TOKEN == undefined) {
28+
return REDIRECT_TO_LOGIN;
29+
}
30+
31+
if (!await isValidToken(TOKEN.value)) {
32+
REDIRECT_TO_LOGIN.cookies.delete("TOKEN");
33+
return REDIRECT_TO_LOGIN;
34+
}
35+
36+
return NextResponse.next();
37+
38+
}
39+
40+
export const config = {
41+
// matcher: /\/^(?!api\/.*|_next\/static\/.*|_next\/image\/.*|favicon.ico|sitemap.xml|robots.txt)$/,
42+
matcher: "/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt|login|register).*)",
43+
}
44+

0 commit comments

Comments
 (0)