From 1f14d8d341496704f8a1c69f51c21fd8ca3c90bc Mon Sep 17 00:00:00 2001 From: Szymon Gladysz Date: Tue, 25 Apr 2023 13:36:59 +0200 Subject: [PATCH 1/2] Added forgotten redirect/notFound fields into gsspWithNonce function --- apps/e2e/components/InternalTestLinks.tsx | 26 +++++++++++ apps/e2e/components/TestNavigation.tsx | 12 +++++ apps/e2e/pages/gssp-not-found/index.tsx | 18 ++++++++ apps/e2e/pages/gssp-redirect/index.tsx | 26 +++++++++++ apps/e2e/pages/gssp-redirect/redirected.tsx | 46 +++++++++++++++++++ apps/e2e/pages/gssp/index.tsx | 15 +----- apps/e2e/pages/index.tsx | 30 ++++-------- apps/e2e/pages/isr/[slug].tsx | 22 +++------ .../src/document/NextPageContext/index.ts | 12 ++++- 9 files changed, 156 insertions(+), 51 deletions(-) create mode 100644 apps/e2e/components/InternalTestLinks.tsx create mode 100644 apps/e2e/components/TestNavigation.tsx create mode 100644 apps/e2e/pages/gssp-not-found/index.tsx create mode 100644 apps/e2e/pages/gssp-redirect/index.tsx create mode 100644 apps/e2e/pages/gssp-redirect/redirected.tsx diff --git a/apps/e2e/components/InternalTestLinks.tsx b/apps/e2e/components/InternalTestLinks.tsx new file mode 100644 index 0000000..e5736e6 --- /dev/null +++ b/apps/e2e/components/InternalTestLinks.tsx @@ -0,0 +1,26 @@ +export const InternalTestLinks = () => { + return ( + + ); +}; + +export default InternalTestLinks; diff --git a/apps/e2e/components/TestNavigation.tsx b/apps/e2e/components/TestNavigation.tsx new file mode 100644 index 0000000..1e339f7 --- /dev/null +++ b/apps/e2e/components/TestNavigation.tsx @@ -0,0 +1,12 @@ +import { InternalTestLinks } from './InternalTestLinks'; + +export const TestNavigation = () => { + return ( + <> +

Internal navigation to other pages

+ + + ); +}; + +export default TestNavigation; diff --git a/apps/e2e/pages/gssp-not-found/index.tsx b/apps/e2e/pages/gssp-not-found/index.tsx new file mode 100644 index 0000000..e83efcb --- /dev/null +++ b/apps/e2e/pages/gssp-not-found/index.tsx @@ -0,0 +1,18 @@ +import Layout from 'components/Layout'; +import { gsspWithNonce } from '@next-safe/middleware/dist/document'; + +export const getServerSideProps = gsspWithNonce(async (ctx) => { + return { + notFound: true, + }; +}); + +const Page = () => { + return ( + + Page should show 404 error + + ); +}; + +export default Page; diff --git a/apps/e2e/pages/gssp-redirect/index.tsx b/apps/e2e/pages/gssp-redirect/index.tsx new file mode 100644 index 0000000..7b1562a --- /dev/null +++ b/apps/e2e/pages/gssp-redirect/index.tsx @@ -0,0 +1,26 @@ +import Prose from 'components/Prose'; +import Layout from 'components/Layout'; +import Hydrated from 'components/Hydrated'; +import StyleElem from 'components/StyleElem'; +import StyleAttr from 'components/StyleAttr'; +import { gsspWithNonce } from '@next-safe/middleware/dist/document'; +import TestNavigation from '../../components/TestNavigation'; + +export const getServerSideProps = gsspWithNonce(async (ctx) => { + return { + redirect: { + destination: '/gssp-redirect/redirected', + permanent: false, + }, + }; +}); + +const Page = () => { + return ( + + Page should redirect to /gssp-redirected + + ); +}; + +export default Page; diff --git a/apps/e2e/pages/gssp-redirect/redirected.tsx b/apps/e2e/pages/gssp-redirect/redirected.tsx new file mode 100644 index 0000000..b88afa4 --- /dev/null +++ b/apps/e2e/pages/gssp-redirect/redirected.tsx @@ -0,0 +1,46 @@ +import "twin.macro"; +import { gsspWithNonce } from "@next-safe/middleware/dist/document"; +import Prose from '../../components/Prose'; +import Hydrated from '../../components/Hydrated'; +import StyleElem from '../../components/StyleElem'; +import StyleAttr from '../../components/StyleAttr'; +import TestNavigation from '../../components/TestNavigation'; +import Layout from '../../components/Layout'; + +export const getServerSideProps = gsspWithNonce(async (ctx) => { + return { + props: {}, + }; +}); + +const Page = () => { + + return ( + + +

A Page with getServerSideProps (redirected)

+ +

+ It get's prerendered per request and has access to request and + response data +

+

+ That's why it can use Nonce-based CSP, it has the chance to set a + fresh nonce as attribute to scripts on each request. +

+

Inline Styles

+ + Hi, i am styled with by an inline style tag. If I am teal, I am + trusted by CSP + + + Hi, i am styled with by an inline style attribute, If I am blue + , I am trusted by CSP + + +
+
+ ); +}; + +export default Page; diff --git a/apps/e2e/pages/gssp/index.tsx b/apps/e2e/pages/gssp/index.tsx index 2e3f009..5a8837d 100644 --- a/apps/e2e/pages/gssp/index.tsx +++ b/apps/e2e/pages/gssp/index.tsx @@ -5,6 +5,7 @@ import Hydrated from "components/Hydrated"; import StyleElem from "components/StyleElem"; import StyleAttr from "components/StyleAttr"; import { gsspWithNonce } from "@next-safe/middleware/dist/document"; +import TestNavigation from "../../components/TestNavigation"; export const getServerSideProps = gsspWithNonce(async (ctx) => { return { @@ -35,19 +36,7 @@ const Page = () => { Hi, i am styled with by an inline style attribute, If I am blue , I am trusted by CSP -

Internal navigation to other pages

- + ); diff --git a/apps/e2e/pages/index.tsx b/apps/e2e/pages/index.tsx index 12d9ce9..02063b9 100644 --- a/apps/e2e/pages/index.tsx +++ b/apps/e2e/pages/index.tsx @@ -1,6 +1,7 @@ -import Prose from "components/Prose"; -import Container from "components/Container"; -import Hydrated from "components/Hydrated"; +import Prose from 'components/Prose'; +import Container from 'components/Container'; +import Hydrated from 'components/Hydrated'; +import InternalTestLinks from '../components/InternalTestLinks'; // pages without a data fetching function are static pages and must use a Hash-based CSP. const Page = () => { @@ -10,28 +11,15 @@ const Page = () => {

@next-safe/middleware e2e app

- A Next.js app to test the strict CSP capabilities of the{" "} + A Next.js app to test the strict CSP capabilities of the{' '} @next-safe/middleware - {" "} + {' '} package.

Prerendering strategies:

This page has no data fetching method

- +

With Mantine:

diff --git a/apps/e2e/pages/isr/[slug].tsx b/apps/e2e/pages/isr/[slug].tsx index c6f29b4..97ae1f7 100644 --- a/apps/e2e/pages/isr/[slug].tsx +++ b/apps/e2e/pages/isr/[slug].tsx @@ -1,9 +1,9 @@ -import Link from "next/link"; -import Prose from "components/Prose"; -import Layout from "components/Layout"; -import Hydrated from "components/Hydrated"; -import StyleElem from "components/StyleElem"; -import StyleAttr from "components/StyleAttr"; +import Prose from 'components/Prose'; +import Layout from 'components/Layout'; +import Hydrated from 'components/Hydrated'; +import StyleElem from 'components/StyleElem'; +import StyleAttr from 'components/StyleAttr'; +import TestNavigation from '../../components/TestNavigation'; export const getStaticPaths = async () => { // as long as we build-time prerender at least one path, it will work with Hash-based strict CSP. @@ -63,15 +63,7 @@ const Page = ({ random, revalidate }) => { Hi, i am styled with by an inline style attribute, If I am{" "} fuchsia, I am trusted by CSP -

Internal navigation to other pages:

-
    -
  • - Page with getStaticProps -
  • -
  • - Page with getServerSideProps -
  • -
+ ); diff --git a/packages/next-safe-middleware/src/document/NextPageContext/index.ts b/packages/next-safe-middleware/src/document/NextPageContext/index.ts index 8297afb..118085c 100644 --- a/packages/next-safe-middleware/src/document/NextPageContext/index.ts +++ b/packages/next-safe-middleware/src/document/NextPageContext/index.ts @@ -11,10 +11,18 @@ export function gsspWithNonce< ): GetServerSideProps

{ return async (ctx) => { const gsspResult = await getServerSideProps(ctx); + const nonce = getCreateCtxNonceIdempotent(ctx); + if ("notFound" in gsspResult) { + const notFound = await gsspResult.notFound; + return { props: { nonce }, notFound: notFound }; + } + if ("redirect" in gsspResult) { + const redirect = await gsspResult.redirect; + return { props: { nonce }, redirect: redirect }; + } if ("props" in gsspResult) { - const nonce = getCreateCtxNonceIdempotent(ctx); const props = await gsspResult.props; - return { props: { ...props, nonce } }; + return { props: { ...props, nonce }}; } }; } From 5ec794c3a4af3e426c0ecf732efa96d4316fc4ef Mon Sep 17 00:00:00 2001 From: Szymon Gladysz Date: Tue, 25 Apr 2023 13:46:40 +0200 Subject: [PATCH 2/2] Added changeset --- .changeset/red-crabs-tickle.md | 7 +++++++ apps/e2e/pages/gssp-redirect/index.tsx | 5 ----- apps/e2e/pages/index.tsx | 8 ++++---- 3 files changed, 11 insertions(+), 9 deletions(-) create mode 100644 .changeset/red-crabs-tickle.md diff --git a/.changeset/red-crabs-tickle.md b/.changeset/red-crabs-tickle.md new file mode 100644 index 0000000..a538e84 --- /dev/null +++ b/.changeset/red-crabs-tickle.md @@ -0,0 +1,7 @@ +--- +"e2e": patch +"@next-safe/middleware": patch +--- + +fix(middleware): Added forgotten redirect/notFound fields into gsspWithNonce function. +fix(e2e): Aadded test pages to test redirect/notFound fields in gsspWithNonce. diff --git a/apps/e2e/pages/gssp-redirect/index.tsx b/apps/e2e/pages/gssp-redirect/index.tsx index 7b1562a..ad44605 100644 --- a/apps/e2e/pages/gssp-redirect/index.tsx +++ b/apps/e2e/pages/gssp-redirect/index.tsx @@ -1,10 +1,5 @@ -import Prose from 'components/Prose'; import Layout from 'components/Layout'; -import Hydrated from 'components/Hydrated'; -import StyleElem from 'components/StyleElem'; -import StyleAttr from 'components/StyleAttr'; import { gsspWithNonce } from '@next-safe/middleware/dist/document'; -import TestNavigation from '../../components/TestNavigation'; export const getServerSideProps = gsspWithNonce(async (ctx) => { return { diff --git a/apps/e2e/pages/index.tsx b/apps/e2e/pages/index.tsx index 02063b9..d1c0f93 100644 --- a/apps/e2e/pages/index.tsx +++ b/apps/e2e/pages/index.tsx @@ -11,10 +11,10 @@ const Page = () => {

@next-safe/middleware e2e app

- A Next.js app to test the strict CSP capabilities of the{' '} + A Next.js app to test the strict CSP capabilities of the{" "} @next-safe/middleware - {' '} + {" "} package.

Prerendering strategies:

@@ -28,13 +28,13 @@ const Page = () => {
  • With getStaticProps - {' '} + {" "} (Hash-based)
  • With getServerSideProps - {' '} + {" "} (Nonce-based)