IP protection in Middleware #3632
-
I am trying to block specific countries within my middleware but cannot find the right piece of documentation. Can someone help me? My current code is the following: import arcjet, { createMiddleware, detectBot, shield } from '@arcjet/next';
import NextAuth from 'next-auth';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import type { NextAuthConfig, NextAuthRequest } from 'next-auth';
import authConfig from '@/lib/auth/auth.config';
import { blockedCountries } from '@/lib/utils/blockedCountries';
export const config = {
// matcher tells Next.js which routes to run the middleware on.
// This runs the middleware on all routes except for static assets.
matcher: ['/((?!_next/static|_next/image|favicon.ico/auth).*)'],
};
const aj = arcjet({
key: process.env.ARCJET_KEY!,
characteristics: ['ip.src'], // track requests by IP address
rules: [
// Protect against common attacks with Arcjet Shield
shield({
mode: 'LIVE', // will block requests. Use "DRY_RUN" to log only
}),
detectBot({
mode: 'LIVE', // will block requests. Use "DRY_RUN" to log only
// Block all bots except the following
allow: [
'CATEGORY:SEARCH_ENGINE', // Google, Bing and other search engines
// See the full list at https://arcjet.com/bot-list
'CATEGORY:MONITOR', // Uptime monitoring services
'CATEGORY:PREVIEW', // Link previews e.g. Slack, Discord
],
}),
slidingWindow({
mode: 'LIVE', // will block requests. Use "DRY_RUN" to log only
interval: 60, // 60 seconds sliding window
max: 100, // allow a maximum of 100 requests
}),
],
});
const { auth } = NextAuth(authConfig satisfies NextAuthConfig);
const nextAuthMatchers = [
/^\/dashboard\/workspaces(\/.*)?$/,
/^\/dashboard\/profile(\/.*)?$/,
];
export const authMiddleware = auth(async (req: NextAuthRequest) => {
// Continue with the authentication check for specific routes.
if (!req.auth && nextAuthMatchers.some((matcher) => matcher.test(req.nextUrl.pathname))) {
return Response.redirect(new URL('/sign-in', req.nextUrl));
}
});
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
export default createMiddleware(aj, authMiddleware); |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Hi @lorenzobalzani - thanks for reaching out! To do this you will need to call the Arcjet Here's a modified version of your code where requests from China will be blocked. You can add additional country codes into the array to block them. There are other examples at https://docs.arcjet.com/blueprints/ip-geolocation import arcjet, { createMiddleware, detectBot, shield } from '@arcjet/next';
import NextAuth from 'next-auth';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import type { NextAuthConfig, NextAuthRequest } from 'next-auth';
import authConfig from '@/lib/auth/auth.config';
import { blockedCountries } from '@/lib/utils/blockedCountries';
export const config = {
// matcher tells Next.js which routes to run the middleware on.
// This runs the middleware on all routes except for static assets.
matcher: ['/((?!_next/static|_next/image|favicon.ico/auth).*)'],
};
const aj = arcjet({
key: process.env.ARCJET_KEY!,
characteristics: ['ip.src'], // track requests by IP address
rules: [
// Protect against common attacks with Arcjet Shield
shield({
mode: 'LIVE', // will block requests. Use "DRY_RUN" to log only
}),
detectBot({
mode: 'LIVE', // will block requests. Use "DRY_RUN" to log only
// Block all bots except the following
allow: [
'CATEGORY:SEARCH_ENGINE', // Google, Bing and other search engines
// See the full list at https://arcjet.com/bot-list
'CATEGORY:MONITOR', // Uptime monitoring services
'CATEGORY:PREVIEW', // Link previews e.g. Slack, Discord
],
}),
slidingWindow({
mode: 'LIVE', // will block requests. Use "DRY_RUN" to log only
interval: 60, // 60 seconds sliding window
max: 100, // allow a maximum of 100 requests
}),
],
});
const { auth } = NextAuth(authConfig satisfies NextAuthConfig);
const nextAuthMatchers = [
/^\/dashboard\/workspaces(\/.*)?$/,
/^\/dashboard\/profile(\/.*)?$/,
];
export default auth(async (req) => {
const decision = await aj.protect(req);
// If the request IP is from a blocked country, return a 403 response
if (
decision.ip.hasCountry() &&
["CN"].includes(decision.ip.country)
) {
return Response.json(
{ error: "Country blocked" },
{ status: 403 },
);
}
// Continue with the authentication check for specific routes.
if (!req.auth && nextAuthMatchers.some((matcher) => matcher.test(req.nextUrl.pathname))) {
return Response.redirect(new URL('/sign-in', req.nextUrl));
}
}); |
Beta Was this translation helpful? Give feedback.
Hi @lorenzobalzani - thanks for reaching out! To do this you will need to call the Arcjet
protect()
method from within theauthMiddleware
. Using ourcreateMiddleware
wrapper is useful if you just want the default behavior, but for something custom like the IP address country lookup you'll need to inspect the decision.Here's a modified version of your code where requests from China will be blocked. You can add additional country codes into the array to block them. There are other examples at https://docs.arcjet.com/blueprints/ip-geolocation