Create a Middleware that checks user login. Here, I have already prepared a BackEnd processing server .
So in this article, we only need to fetch the api and process the returned value. If you have not seen the previous article about Middleware, you can review this link: Create A Middleware In NextJS 13 - hoanguyenit.com
*CREATE A API FOLDER IN PROJECT *
- _app/api/login/route.ts _ In this route.ts file , we will send ( username , _password _) to the backend server to check login. If correct, access_token will be returned
import { NextRequest, NextResponse } from "next/server";
type RequestBody = {
email: string;
password: string;
};
export async function POST(request: NextRequest) {
const body: RequestBody = await request.json();
const value = {
email: body.email,
password: body.password,
};
const res = await fetch("https://127.0.0.1:8000/api/auth/login", {
method: "POST",
mode: "cors",
cache: "no-cache",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(value),
});
const data = await res.json();
if (data.success) {
// Then set a cookie
const response = NextResponse.json(
{
success: data.success,
},
{ status: 200 }
);
response.cookies.set({
name: "login",
value: "true",
httpOnly: true,
});
response.cookies.set({
name: "access_token",
value: data.access_token, //token value here
httpOnly: true,
maxAge: data.expires_in,
});
return response;
}
return new NextResponse(null, {
status: 404,
statusText: "Bad request",
headers: {
"Content-Type": "text/plain",
},
});
}
The backend will return data like ( access_token , expires_in ), we can use this data to store it as cookies .
const response = NextResponse.json(
{
success: data.success,
},
{ status: 200 }
);
response.cookies.set({
name: "login",
value: "true",
httpOnly: true,
});
response.cookies.set({
name: "access_token",
value: data.access_token, //token value here
httpOnly: true,
maxAge: data.expires_in,
});
CREATE A MIDDLEWARE
- middleware.ts : used to check access_token , whether it exists or not by using request.cookie.get('access_token')
import { NextRequest, NextResponse } from "next/server";
const allow_origin_lists :string[] = process.env.NODE_ENV==='production'?['https://hoanguyenit.com','https://100daysofcode.hoanguyenit.com']:
['https://www.google.com','http://localhost:3000','http://127.0.0.1:3000']
export default function middleware(request: NextRequest){
const login = request.cookies.get("login");
const check_login= !login?.value? false: true
const access_token = request.cookies.get("access_token");
const check_token = !access_token?.value? false: true
const origin: string | null = request.headers.get('origin')
const res = NextResponse.next()
// console.log(request.nextUrl.pathname);
const res_404 = new NextResponse(null,
{
status: 404,
statusText:"Bad request",
headers:{
'Content-Type':'text/plain'
}
})
if(origin && !allow_origin_lists.includes(origin)){
return res_404;
}
if(!check_login && !check_token){
return res_404;
}
console.log("origin",origin);
res.headers.append('Access-Control-Allow-Credentials', "true")
res.headers.append('Access-Control-Allow-Origin', origin)
res.headers.append('Access-Control-Allow-Methods', 'GET,DELETE,PATCH,POST,PUT')
res.headers.append(
'Access-Control-Allow-Headers',
'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version'
)
return res;
}
export const config = {
matcher:[
'/api/categories:path*',
'/api/post:path*',
'/api/user:path*'
]
}
In the above code, we check the values in the cookie that we saved in the login section above
const login = request.cookies.get("login");
const check_login= !login?.value? false: true
const access_token = request.cookies.get("access_token");
const check_token = !access_token?.value? false: true
//nếu không đúng trả về status 404
if(!check_login && !check_token){
return res_404;
}
Here, we need middleware to request the following api routes:
export const config = {
matcher:[
'/api/categories:path*',
'/api/post:path*',
'/api/user:path*'
]
}
Okay so we have created Middleware.
Now we need to create a user api folder to get that user's information. If everything in the middleware is correct, it will allow us to call api/user/
- app/api/user/route.ts
import { NextRequest, NextResponse } from 'next/server'
type ResponseBody = { errors: { message: string }[] } | { username: string };
async function getUserByValidSessionToken(token : string){
const res = await fetch('http://127.0.0.1:8000/api/auth/user-profile',{
headers: {
"Content-Type": "application/json",
"Authorization":"Bearer "+token
},
});
const data = await res.json();
return {
username: data.name
}
}
export async function GET(
request: NextRequest
): Promise<NextResponse<ResponseBody>> {
const token = request.cookies.get("access_token");
const user = !token?.value
? undefined
: await getUserByValidSessionToken(token.value);
if (!user) {
return NextResponse.json({
errors: [{ message: "User not found by session token" }],
});
}
return NextResponse.json({
username: user.username,
});
Get the access_token value in the cookie
const token = request.cookies.get("access_token");
const user = !token?.value
? undefined
: await getUserByValidSessionToken(token.value);
Write fucntion fetch api + token
const res = await fetch('http://127.0.0.1:8000/api/auth/user-profile',{
headers: {
"Content-Type": "application/json",
"Authorization":"Bearer "+token
},
});
Okay that's it, you can develop further
- Check the token's expiration time, if the Token expires, you can force the user to log in again
- If the BackEnd side has a refresh_token attached , then take the refresh_token to see if it's still valid, send it to BackEnd , to get a new access_token You can see more about JWT(Json Web Token) In Node.Js The article : Check Login Using Middleware With NextJS 13
Top comments (0)