The User-Agent
HTTP header provides information about the client’s browser and operating system. You can restrict access to your Next.js application based on its value. For example, by allowing only certain User Agents, you can protect your site from bots and scrapers.
In this article, you will learn two methods to control User Agents in Next.js. Let’s dive in!
Why Control User Agents?
There are at least three good reasons to accept only a limited set of User Agents in your Next.js app:
- Improved security: Protects your site from potential security vulnerabilities and works as an entry-level anti-bot and anti-scraping measure.
- Enhanced performance: Ensures that only well-performing browsers and operating systems your app support can see your web app.
- Consistent user experience: Maintains a consistent user experience across different devices and browsers, making sure that your application looks and functions as intended for the targeted user agents.
You now know the reasons why dealing with User Agents. New browser versions get released every day, and you need a tool that allows you to parse and verify the User-Agent
HTTP header consistently. This is what UAParser.js is all about!
What Is UAParser.js?
ua-parser-js
is an npm JavaScript library to detect browser, engine, OS, CPU, and device type/model from the string value contained in the User-Agent
header of a request. It can be used either in the client or in the server.
The package support User Agents from all device types, including Windows, Linux, macOS, iOS, and Android.
Restricting User Agents in Next.js
Before getting started, make sure to meet the prerequisites below:
- A Next.js 12.2+ app
-
ua-parser-js
installed
Add ua-parser-js
to your project’s dependencies with:
npm install ua-parser-js
Let’s now see how to allow only specific User Agents in Next.js on a single page or on all page routes.
On a Single Page
You can make a specific page on a Next.js site accessible only from requests from specific devices by updating getServerSideProps()
or getStaticProps()
as below:
import * as UAParser from "ua-parser-js" // other imports... // React component... export async function getServerSideProps(context) { // get the value inside the "user-agent" header const userAgent = context.req.headers["user-agent"] // parse the user agent const parsedUserAgent = new UAParser.UAParser(userAgent) // verify that the user agent comes from a real browser if (parsedUserAgent.getBrowser().name === undefined) { throw new Error(`Invalid User-Agent: ${userAgent}`) } // data retriaval logic ... return { props: { // ... }, } }
First, make sure to import ua-parser-js
. Then, retrieve the User-Agent
header value in the Next.js rendering function and pass it to the UaParser()
function. This will return an object exposing several methods to extract the required information from the header. Use them to implement your User Agent validation logic.
On All Pages
If you want to restrict User Agents on all routes of your app, you can use a Next.js middleware. This is a function that allows you to perform specific logic before a request is completed.
In other words, it intercepts any incoming request and gives you the possibility to rewrite, redirect, and modify the request or response headers, or respond directly.
You can create a middleware by adding a middleware.js
(or .ts
in TypeScript) in the root folder of your project. In detail, place it at the same level as pages
or app
, or inside src
if applicable.
This is what your middleware.js
should look like:
// src/middleware.js import { NextResponse } from "next/server" import * as UAParser from "ua-parser-js" export function middleware(request: NextRequest) { // get the user Agent and parse it const userAgent = request.headers.get("user-agent") || undefined const userAgentParsed = new UAParser.UAParser(userAgent) // if the User Agent does not come from a browser, return // a 403 Forbidden error response if (userAgentParsed.getBrowser().name === undefined) { return NextResponse.json( { message: "Forbidden", }, { status: 403, }, ) } return NextResponse.next() } // running the middleware on all paths export const config = { /* * Match all request paths except for the ones starting with: * - api (API routes) * - _next/static (static files) * - _next/image (image optimization files) * - favicon.ico (favicon file) */ matcher: '/((?!api|_next/static|_next/image|favicon.ico).*)', }
The middleware()
function contains the logic to apply before each request is completed. Note that matcher
allows you to filter the request paths to run the middleware function on. This will protect all your pages from invalid User Agents.
Et voilà! You just learned how to deal with User Agents in Next.js!
Conclusion
In this article, you learned what User Agents are, why to control them, and how to allow only requests with specific values in Next.js. Thanks toua-parser-js
you can parse User Agents in JavaScript, and here you saw how to use it to restrict UA on a single page or on all pages.
Thanks for reading! I hope you found this article helpful.