diff --git a/src/content/docs/nosecone/reference.mdx b/src/content/docs/nosecone/reference.mdx index 8ac0a43..e739731 100644 --- a/src/content/docs/nosecone/reference.mdx +++ b/src/content/docs/nosecone/reference.mdx @@ -71,7 +71,19 @@ import StaticOptOut from "@/snippets/nosecone/reference/next-js/StaticOptOut.mdx -Additional resources: +### Chaining middleware + +If you are using multiple Next.js middleware functions, you can chain them +together to add the security headers. + +This example shows how to chain Arcjet with [Auth.js](https://authjs.dev) +middleware: + +import ChainedMiddleware from "@/snippets/nosecone/reference/next-js/ChainedMiddleware.mdx"; + + + +### Additional resources - [Next.js Content-Security-Policy guide](https://nextjs.org/docs/app/building-your-application/configuring/content-security-policy) diff --git a/src/snippets/nosecone/quick-start/next-js/Step2.mdx b/src/snippets/nosecone/quick-start/next-js/Step2.mdx index 5f6d593..39eddfb 100644 --- a/src/snippets/nosecone/quick-start/next-js/Step2.mdx +++ b/src/snippets/nosecone/quick-start/next-js/Step2.mdx @@ -1,4 +1,4 @@ -import { Code } from "@astrojs/starlight/components"; +import { Aside, Code } from "@astrojs/starlight/components"; import SelectableContent from "@/components/SelectableContent"; import Step2MiddlewareTS from "./Step2Middleware.ts?raw"; @@ -12,12 +12,6 @@ import Step2LayoutNoCacheJS from "./Step2LayoutNoCache.js?raw"; Nosecone applies headers to all your routes via middleware in your Next.js application. -:::note -We recommend you remove any `export const config = ...` from your middleware so -Nosecone will run on every route. This ensures the headers are applied to all -requests. -::: -
@@ -27,6 +21,10 @@ requests.
+We recommend you remove any `export const config = ...` from your middleware so +Nosecone will run on every route. This ensures the headers are applied to all +requests. + You also need to opt-out of static generation in your application. See the `@nosecone/next` [reference guide](/nosecone/reference#nextjs-security-headers-middleware) for more details @@ -68,3 +66,12 @@ To opt-out of static generation, modify your layout file with the following: /> + +We recommend you remove any `export const config = ...` from your middleware so +Nosecone will run on every route. This ensures the headers are applied to all +requests. + + diff --git a/src/snippets/nosecone/reference/next-js/ChainedMiddleware.js b/src/snippets/nosecone/reference/next-js/ChainedMiddleware.js new file mode 100644 index 0000000..9501261 --- /dev/null +++ b/src/snippets/nosecone/reference/next-js/ChainedMiddleware.js @@ -0,0 +1,27 @@ +import { createMiddleware, defaults } from "@nosecone/next"; +import { auth } from "./auth"; + +// Nosecone security headers configuration +// https://docs.arcjet.com/nosecone/quick-start +const noseconeOptions = { + ...defaults, +}; + +const securityHeaders = createMiddleware(noseconeOptions); + +// @ts-ignore: This type will be correct when used in a real app +export default auth(async (req) => { + // Redirect to signin page if not authenticated + // Example from https://authjs.dev/getting-started/session-management/protecting + if (!req.auth && !req.nextUrl.pathname.startsWith("/auth")) { + const newUrl = new URL("/auth/signin", req.nextUrl.origin); + return Response.redirect(newUrl); + } + + // Otherwise return security headers + return securityHeaders(); +}); + +export const config = { + matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"], +}; diff --git a/src/snippets/nosecone/reference/next-js/ChainedMiddleware.mdx b/src/snippets/nosecone/reference/next-js/ChainedMiddleware.mdx new file mode 100644 index 0000000..be4470d --- /dev/null +++ b/src/snippets/nosecone/reference/next-js/ChainedMiddleware.mdx @@ -0,0 +1,14 @@ +import { Code } from "@astrojs/starlight/components"; +import SelectableContent from "@/components/SelectableContent"; + +import ChainedMiddlewareTS from "./ChainedMiddleware.ts?raw"; +import ChainedMiddlewareJS from "./ChainedMiddleware.js?raw"; + + +
+ +
+
+ +
+
diff --git a/src/snippets/nosecone/reference/next-js/ChainedMiddleware.ts b/src/snippets/nosecone/reference/next-js/ChainedMiddleware.ts new file mode 100644 index 0000000..d648160 --- /dev/null +++ b/src/snippets/nosecone/reference/next-js/ChainedMiddleware.ts @@ -0,0 +1,32 @@ +import { + type NoseconeOptions, + createMiddleware, + defaults, +} from "@nosecone/next"; +// @ts-ignore: Import your auth library. See https://authjs.dev +import { auth } from "./auth"; + +// Nosecone security headers configuration +// https://docs.arcjet.com/nosecone/quick-start +const noseconeOptions: NoseconeOptions = { + ...defaults, +}; + +const securityHeaders = createMiddleware(noseconeOptions); + +// @ts-ignore: This type will be correct when used in a real app +export default auth(async (req) => { + // Redirect to signin page if not authenticated + // Example from https://authjs.dev/getting-started/session-management/protecting + if (!req.auth && !req.nextUrl.pathname.startsWith("/auth")) { + const newUrl = new URL("/auth/signin", req.nextUrl.origin); + return Response.redirect(newUrl); + } + + // Otherwise return security headers + return securityHeaders(); +}); + +export const config = { + matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"], +};