In this short article, i will be writing about how to build a middleware with nextjs.
I recently built a full blown backend service with nextjs, and i was really blown away with how far gone nextjs is.
You need to have basic knowledge of javascript and nodejs to follow this article.
To get started, you need to
1. Create a nextjs project from your terminal using the command below
npx create-next-app@latest
After running this command, you will get some prompt to configure your project, do that.
After creating the project,
2. Install necessary dependencies by running npm install in your terminal
We will be installing just one package library for authentication, which is jose, an alternative could have been jsonwebtoken, but nextjs middleware runs on the browser, so the edge runtime doesn't implement a bunch of Node.js APIs
3. Start your project in development mode using the command below
npm run dev
4. Create a middleware.js file
Create a middleware.js file at the root of your project, if you're using the /src directory, create the file inside the /src directory
5. Export a middleware function from the file
// /middleware.js export const middleware = async (req) => { try { } catch(error){ console.log(error) } }
6. Extract token from request header
// /middleware.js import { NextResponse } from 'next/server' export const middleware = async (req) => { try { const header = req.headers.get('authorization'); if(!header) return NextResponse.json({ status:'error' statusCode: 400, message:'unauthenticated' }) const token = header.split(" ")[1]; if(!token) return NextResponse.json({ status:'error' statusCode: 401, message:'You are not logged in' }) } catch(error){ console.log(error) } }
7. Verify the token using jose
// /middleware.js import { NextResponse } from 'next/server'; import * as jose from 'jose' export const middleware = async (req) => { try { const header = req.headers.get('authorization'); if(!header) return NextResponse.json({ status:'error' statusCode: 400, message:'unauthenticated' }) const token = header.split(" ")[1]; if(!token) return NextResponse.json({ status:'error' statusCode: 401, message:'You are not logged in' }) const { payload } = await jose.jwtVerify( token, new TextEncoder().encode(process.env.NEXT_PUBLIC_JWT_KEY) ); // your encoded data will be inside the payload object. } catch(error){ console.log(error) } }
8. Extract data from verified token and set it in the request header
// /middleware.js import { NextResponse } from 'next/server'; import * as jose from 'jose' export const middleware = async (req) => { try { const header = req.headers.get('authorization'); if(!header) return NextResponse.json({ status:'error' statusCode: 400, message:'unauthenticated' }) const token = header.split(" ")[1]; if(!token) return NextResponse.json({ status:'error' statusCode: 401, message:'You are not logged in' }) const { payload } = await jose.jwtVerify( token, new TextEncoder().encode(process.env.NEXT_PUBLIC_JWT_KEY) ); const requestHeaders = new Headers(req.headers) requestHeaders.set('user', payload.id) } catch(error){ console.log(error) } }
9. Call the next() function and pass the updated request header
// /middleware.js import { NextResponse } from 'next/server'; import * as jose from 'jose' export const middleware = async (req) => { try { const header = req.headers.get('authorization'); if(!header) return NextResponse.json({ status:'error' statusCode: 400, message:'unauthenticated' }) const token = header.split(" ")[1]; if(!token) return NextResponse.json({ status:'error' statusCode: 401, message:'You are not logged in' }) const { payload } = await jose.jwtVerify( token, new TextEncoder().encode(process.env.NEXT_PUBLIC_JWT_KEY) ); const requestHeaders = new Headers(req.headers) requestHeaders.set('user', payload.id) return NextResponse.next({ request: { headers: requestHeaders } }) } catch(error){ console.log(error) } }
10. Finally, you need to export a config object from the middleware file that contains configurations about the routes you want to protect.
// /middleware.js import { NextResponse } from 'next/server'; import * as jose from 'jose' export const config = { matcher:[ // contain list of routes you want to protect, e.g /api/users/:path* ] } export const middleware = async (req) => { try { const header = req.headers.get('authorization'); if(!header) return NextResponse.json({ status:'error' statusCode: 400, message:'unauthenticated' }) const token = header.split(" ")[1]; if(!token) return NextResponse.json({ status:'error' statusCode: 401, message:'You are not logged in' }) const { payload } = await jose.jwtVerify( token, new TextEncoder().encode(process.env.NEXT_PUBLIC_JWT_KEY) ); const requestHeaders = new Headers(req.headers) requestHeaders.set('user', payload.id) return NextResponse.next({ request: { headers: requestHeaders } }) } catch(error){ console.log(error) } }
I hope you find this 10 steps helpful, let me know what you think about this method in the comment section, and feel free to share if a better way to achieve this too.
Thank you.
Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.
Copyright© 2022 湘ICP备2022001581号-3