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 ourcreateMiddlewarewrapper 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