Skip to content

Commit

Permalink
Merge pull request #93 from SocialGouv/fix/csp-and-cookies-attributes
Browse files Browse the repository at this point in the history
Fix: sentry build fail issue, csp and cookies attributes
  • Loading branch information
ClementNumericite authored Jun 21, 2024
2 parents 9fb5423 + ce883d7 commit 5370a63
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 66 deletions.
14 changes: 7 additions & 7 deletions webapp-next/components/landing/NavbarLanding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,25 @@ import {
Flex,
Image,
Box,
useBreakpointValue,
Text,
useDisclosure,
Wrap,
WrapItem,
CloseButton,
Link,
} from "@chakra-ui/react";

import NextLink from "next/link";
import { useRouter } from "next/router";
import cookie from "js-cookie";
import { ELASTIC_API_KEY_NAME } from "@/utils/tools";
import useSWR from "swr";

export default function NavbarLanding() {
const { isOpen, onOpen, onClose } = useDisclosure();

const router = useRouter();

const hasApiKey = !!cookie.get(ELASTIC_API_KEY_NAME);
const { data: user, isLoading: isLoadingUser } = useSWR(
"/api/auth/user",
(...args) => fetch(...args).then((res) => res.json())
);

const links = [
{ label: "Accueil", path: "/" },
Expand Down Expand Up @@ -72,7 +72,7 @@ export default function NavbarLanding() {
<HamburgerIcon onClick={onOpen} display={["inline", "none"]} />
)}
</Flex>
{hasApiKey ? (
{!isLoadingUser && !!user ? (
<Flex as="nav" bg="white">
<Button
as={NextLink}
Expand Down
1 change: 0 additions & 1 deletion webapp-next/components/layouts/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ export function Menu() {
label: 'Déconnexion',
icon: '/icons/log-out.svg',
onClick: () => {
cookie.remove(ELASTIC_API_KEY_NAME);
triggerInvalidateApiKey({
username: context.user.username as string
}).then(() => {
Expand Down
17 changes: 2 additions & 15 deletions webapp-next/components/login/FormLogin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,10 @@ export const FormLogin = () => {
const handleModalTermsAccept = async () => {
if (code) {
await triggerCreateUser({ username, versionCGU: "1" });
const res = (await triggerVerify({
(await triggerVerify({
username: username,
code: code.toString(),
})) as any;
const result = await res.json();
cookie.set(ELASTIC_API_KEY_NAME, result.apiKey.encoded, {
expires: 1,
});
onCloseTerms();
router.push("/bo");
}
Expand All @@ -132,9 +128,6 @@ export const FormLogin = () => {
if (result.firstLogin) {
onOpenTerms();
} else {
cookie.set(ELASTIC_API_KEY_NAME, result.apiKey.encoded, {
expires: 1,
});
router.push("/bo");
}
setIsLoading(false);
Expand All @@ -157,13 +150,7 @@ export const FormLogin = () => {
setIsLoading(true);
const res = (await triggerLogin({ username, password })) as any;
if (res.ok) {
const result = await res.json();
if (process.env.NODE_ENV === "development") {
cookie.set(ELASTIC_API_KEY_NAME, result.encoded, {
expires: 1,
});
router.push("/bo");
}
if (process.env.NODE_ENV === "development") router.push("/bo");
startTimer();
setShowCodeForm(true);
setIsLoading(false);
Expand Down
39 changes: 34 additions & 5 deletions webapp-next/next.config.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,37 @@
const cspHeader = `
default-src 'self' sentry.numericite.eu;
script-src 'self' 'unsafe-eval' 'unsafe-inline';
style-src 'self' 'unsafe-inline';
img-src 'self' blob: data:;
font-src 'self';
object-src 'none';
base-uri 'self';
form-action 'self';
frame-ancestors 'none';
worker-src 'self' blob:;
upgrade-insecure-requests;
`;

/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
output: "standalone"
}

module.exports = nextConfig
output: "standalone",
async headers() {
return [
{
source: "/(.*)",
headers: [
{
key: "Content-Security-Policy",
value: cspHeader.replace(/\n/g, ""),
},
],
},
];
},
};

module.exports = nextConfig;

// Injected content via Sentry wizard below

Expand All @@ -21,7 +47,10 @@ module.exports = withSentryConfig(
silent: true,
org: "numericite",
project: "cm2d-nextjs",
url: "https://sentry.numericite.eu/"
url: "https://sentry.numericite.eu/",
errorHandler: (err, _, compilation) => {
compilation.warnings.push("Sentry CLI Plugin: " + err.message);
},
},
{
// For all available options, see:
Expand Down
4 changes: 3 additions & 1 deletion webapp-next/pages/api/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { sendMail } from '@/utils/mailter';
import {
generateCode,
getCodeEmailHtml,
ELASTIC_API_KEY_NAME
ELASTIC_API_KEY_NAME,
setCookieServerSide
} from '@/utils/tools';
import { Client } from '@elastic/elasticsearch';
import fs from 'fs';
Expand Down Expand Up @@ -74,6 +75,7 @@ export default async function handler(
});

if (process.env.NODE_ENV === 'development') {
setCookieServerSide(res, securityToken.encoded);
res.status(200).json(securityToken);
} else {
tmpCodes[username] = { code: generateCode(), apiKey: securityToken };
Expand Down
7 changes: 7 additions & 0 deletions webapp-next/pages/api/auth/invalidate-api-key.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ELASTIC_API_KEY_NAME } from "@/utils/tools";
import { Client } from "@elastic/elasticsearch";
import fs from "fs";
import type { NextApiRequest, NextApiResponse } from "next";
Expand Down Expand Up @@ -27,6 +28,12 @@ export default async function handler(
username,
});

res.setHeader("Set-Cookie", [
`${ELASTIC_API_KEY_NAME}=; Path=/; HttpOnly; Max-Age=-1; ${
process.env.NODE_ENV !== "development" ? "Secure" : ""
}`,
]);

res.status(200).json(invalidatedApiKey);
} catch (error: any) {
res.status(500).end();
Expand Down
5 changes: 5 additions & 0 deletions webapp-next/pages/api/auth/verify-code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { NextApiRequest, NextApiResponse } from "next";
import fs from "fs";
import path from "path";
import rateLimit from "@/utils/rate-limit";
import { setCookieServerSide } from "@/utils/tools";
const tmpCodes = require("../../../utils/codes");

const limiter = rateLimit({
Expand Down Expand Up @@ -54,6 +55,10 @@ export default async function handler(
firstLogin = true;
}

if (!firstLogin) {
setCookieServerSide(res, codeObj.apiKey.encoded)
}

res.status(200).json({
apiKey:
firstLogin && process.env.NODE_ENV !== "development"
Expand Down
40 changes: 21 additions & 19 deletions webapp-next/sentry.client.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,29 @@

import * as Sentry from "@sentry/nextjs";

Sentry.init({
dsn: "https://c334baad1c926c98296ad34785ece1af@sentry.numericite.eu/3",
if (process.env.NODE_ENV !== "development") {
Sentry.init({
dsn: "https://c334baad1c926c98296ad34785ece1af@sentry.numericite.eu/3",

// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1,

// Setting this option to true will print useful information to the console while you're setting up Sentry.
debug: false,
// Setting this option to true will print useful information to the console while you're setting up Sentry.
debug: false,

replaysOnErrorSampleRate: 1.0,
replaysOnErrorSampleRate: 1.0,

// This sets the sample rate to be 10%. You may want this to be 100% while
// in development and sample at a lower rate in production
replaysSessionSampleRate: 0.1,
// This sets the sample rate to be 10%. You may want this to be 100% while
// in development and sample at a lower rate in production
replaysSessionSampleRate: 0.1,

// You can remove this option if you're not planning to use the Sentry Session Replay feature:
integrations: [
new Sentry.Replay({
// Additional Replay configuration goes in here, for example:
maskAllText: true,
blockAllMedia: true,
}),
],
});
// You can remove this option if you're not planning to use the Sentry Session Replay feature:
integrations: [
new Sentry.Replay({
// Additional Replay configuration goes in here, for example:
maskAllText: true,
blockAllMedia: true,
}),
],
});
}
16 changes: 9 additions & 7 deletions webapp-next/sentry.edge.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@

import * as Sentry from "@sentry/nextjs";

Sentry.init({
dsn: "https://c334baad1c926c98296ad34785ece1af@sentry.numericite.eu/3",
if (process.env.NODE_ENV !== "development") {
Sentry.init({
dsn: "https://c334baad1c926c98296ad34785ece1af@sentry.numericite.eu/3",

// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1,

// Setting this option to true will print useful information to the console while you're setting up Sentry.
debug: false,
});
// Setting this option to true will print useful information to the console while you're setting up Sentry.
debug: false,
});
}
16 changes: 9 additions & 7 deletions webapp-next/sentry.server.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@

import * as Sentry from "@sentry/nextjs";

Sentry.init({
dsn: "https://c334baad1c926c98296ad34785ece1af@sentry.numericite.eu/3",
if (process.env.NODE_ENV !== "development") {
Sentry.init({
dsn: "https://c334baad1c926c98296ad34785ece1af@sentry.numericite.eu/3",

// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1,
// Adjust this value in production, or use tracesSampler for greater control
tracesSampleRate: 1,

// Setting this option to true will print useful information to the console while you're setting up Sentry.
debug: false,
});
// Setting this option to true will print useful information to the console while you're setting up Sentry.
debug: false,
});
}
23 changes: 19 additions & 4 deletions webapp-next/utils/tools.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import moment from "moment";
import { Filters, SearchCategory, View } from "./cm2d-provider";
import { format } from 'date-fns';
import moment from 'moment';
import { Filters, SearchCategory, View } from './cm2d-provider';
import { NextApiResponse } from 'next';

export const viewRefs: { label: string; value: View }[] = [
{ label: "Vue courbe", value: "line" },
Expand Down Expand Up @@ -794,12 +796,25 @@ export function removeAccents(str: string) {
}

export const ELASTIC_API_KEY_NAME =
(process.env.NEXT_PUBLIC_ELASTIC_API_KEY_NAME as string) || "cm2d_api_key";
(process.env.NEXT_PUBLIC_ELASTIC_API_KEY_NAME as string) || 'cm2d_api_key';


export const setCookieServerSide = (
res: NextApiResponse,
securityTokenEncoded: string
) => {
res.setHeader(
"Set-Cookie",
`${ELASTIC_API_KEY_NAME}=${securityTokenEncoded}; path=/; HttpOnly; ${
process.env.NODE_ENV !== "development" ? "Secure;" : ""
}`
);
};

export async function swrPOSTFetch<T>(url: string, { arg }: { arg: T }) {
return fetch(url, {
method: "POST",
body: JSON.stringify(arg),
headers: { "Content-Type": "application/json" },
});
}
}

0 comments on commit 5370a63

Please sign in to comment.