Skip to content

Commit

Permalink
Add nonce to headers to be used in components
Browse files Browse the repository at this point in the history
  • Loading branch information
hursey013 committed Oct 30, 2024
1 parent e81bdd2 commit da969cd
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 17 deletions.
5 changes: 4 additions & 1 deletion src/components/ProgressBar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { headers } from 'next/headers';
import { InfinitySVG } from '@/components/svgs/InfinitySVG';

export function ProgressBar({
export async function ProgressBar({
total, // number representing total length of bar
fill, // number representing how much bar should be filled
threshold1 = 75, // percentage where color should change first, between 0 and 100
Expand All @@ -13,6 +14,7 @@ export function ProgressBar({
threshold2?: number;
changeColors?: boolean;
}) {
const nonce = (await headers()).get('x-nonce') || undefined;
const heightClass = 'height-1';
const percentage = total ? Math.floor((fill / total) * 100) : 100;
let color = 'bg-mint';
Expand All @@ -33,6 +35,7 @@ export function ProgressBar({
className={`${heightClass} radius-pill ${color}`}
style={{ width: `${percentage}%` }}
data-testid="progress"
nonce={nonce}
></div>
{!total && (
<span className="progress__infinity-logo">
Expand Down
3 changes: 2 additions & 1 deletion src/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { stackMiddlewares } from './middlewares/stackMiddlewares';
import { withAuth } from './middlewares/withAuth';
import { withNonce } from './middlewares/withNonce';
import { withCSP } from './middlewares/withCSP';

export default stackMiddlewares([withCSP, withAuth]);
export default stackMiddlewares([withNonce, withCSP, withAuth]);

export const config = {
matcher: [
Expand Down
33 changes: 18 additions & 15 deletions src/middlewares/withCSP.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { MiddlewareFactory } from './types';

export const withCSP: MiddlewareFactory = (next: NextMiddleware) => {
return async (request: NextRequest, _next: NextFetchEvent) => {
const nonce = Buffer.from(crypto.randomUUID()).toString('base64');

const cspHeader = `
if (request.headers.get('x-nonce') != null) {
const nonce = request.headers.get('x-nonce');
const cspHeader = `
default-src 'self';
script-src 'self' 'nonce-${nonce}' 'strict-dynamic' ${process.env.NODE_ENV === 'development' ? "'unsafe-eval'" : ''};
style-src 'self' 'nonce-${nonce}';
Expand All @@ -19,21 +19,24 @@ export const withCSP: MiddlewareFactory = (next: NextMiddleware) => {
${process.env.NODE_ENV !== 'development' ? 'upgrade-insecure-requests;' : ''};
`;

// Replace newline characters and spaces
const contentSecurityPolicyHeaderValue = cspHeader
.replace(/\s{2,}/g, ' ')
.trim();
request.headers.set(
'Content-Security-Policy',
contentSecurityPolicyHeaderValue
);
const response = await next(request, _next);
if (response) {
response.headers.set(
// Replace newline characters and spaces
const contentSecurityPolicyHeaderValue = cspHeader
.replace(/\s{2,}/g, ' ')
.trim();
request.headers.set(
'Content-Security-Policy',
contentSecurityPolicyHeaderValue
);
const response = await next(request, _next);
if (response) {
response.headers.set(
'Content-Security-Policy',
contentSecurityPolicyHeaderValue
);
}
return response;
} else {
return next(request, _next);
}
return response;
};
};
11 changes: 11 additions & 0 deletions src/middlewares/withNonce.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { NextFetchEvent, NextMiddleware, NextRequest } from 'next/server';

import { MiddlewareFactory } from './types';

export const withNonce: MiddlewareFactory = (next: NextMiddleware) => {
return async (request: NextRequest, _next: NextFetchEvent) => {
const nonce = Buffer.from(crypto.randomUUID()).toString('base64');
request.headers.set('x-nonce', nonce);
return next(request, _next);
};
};

0 comments on commit da969cd

Please sign in to comment.