Skip to content

Commit 6f540d3

Browse files
Merge pull request #297 from NHSDigital/feature/CCM-8477_csrf-token-3
CCM-8446: CSRF token verification
2 parents 641fbae + ad0b0ee commit 6f540d3

File tree

25 files changed

+394
-45
lines changed

25 files changed

+394
-45
lines changed

frontend/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,13 @@
2222
"@aws-amplify/backend": "^1.2.0",
2323
"@aws-amplify/ui-react": "^6.3.1",
2424
"@aws-sdk/client-ses": "^3.637.0",
25-
"@edge-csrf/core": "^2.5.2",
26-
"@edge-csrf/nextjs": "^2.5.2",
2725
"aws-amplify": "^6.6.0",
2826
"date-fns": "^4.1.0",
2927
"jwt-decode": "^4.0.0",
3028
"markdown-it": "^13.0.1",
3129
"mimetext": "^3.0.24",
3230
"next": "14.2.13",
31+
"next-client-cookies": "^1.1.1",
3332
"nhs-notify-backend-client": "*",
3433
"nhs-notify-web-template-management-amplify": "*",
3534
"nhs-notify-web-template-management-utils": "*",

frontend/src/__tests__/app/choose-a-template-type/__snapshots__/page.test.tsx.snap

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ exports[`ChooseATemplateTypePage 1`] = `
3838
type="hidden"
3939
value="choose-a-template-type"
4040
/>
41+
<input
42+
name="csrf_token"
43+
readonly=""
44+
type="hidden"
45+
value="no_token"
46+
/>
4147
<div
4248
class="nhsuk-form-group"
4349
>

frontend/src/__tests__/components/forms/ChooseTemplate/__snapshots__/ChooseTemplate.test.tsx.snap

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ exports[`Choose template page renders error component 1`] = `
6363
type="hidden"
6464
value="choose-a-template-type"
6565
/>
66+
<input
67+
name="csrf_token"
68+
readonly=""
69+
type="hidden"
70+
value="no_token"
71+
/>
6672
<div
6773
class="nhsuk-form-group"
6874
>
@@ -215,6 +221,12 @@ exports[`Choose template page selects one radio button at a time 1`] = `
215221
type="hidden"
216222
value="choose-a-template-type"
217223
/>
224+
<input
225+
name="csrf_token"
226+
readonly=""
227+
type="hidden"
228+
value="no_token"
229+
/>
218230
<div
219231
class="nhsuk-form-group"
220232
>

frontend/src/__tests__/components/forms/CopyTemplate/__snapshots__/CopyTemplate.test.tsx.snap

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ exports[`Choose template page renders error component 1`] = `
7575
type="hidden"
7676
value="choose-a-template-type"
7777
/>
78+
<input
79+
name="csrf_token"
80+
readonly=""
81+
type="hidden"
82+
value="no_token"
83+
/>
7884
<div
7985
class="nhsuk-form-group"
8086
>
@@ -228,6 +234,12 @@ exports[`Choose template page selects one radio button at a time 1`] = `
228234
type="hidden"
229235
value="choose-a-template-type"
230236
/>
237+
<input
238+
name="csrf_token"
239+
readonly=""
240+
type="hidden"
241+
value="no_token"
242+
/>
231243
<div
232244
class="nhsuk-form-group"
233245
>

frontend/src/__tests__/components/forms/DeleteTemplate/DeleteTemplate.test.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@ jest.mock('react-dom', () => {
1717
formData: FormData
1818
) => Promise<TemplateFormState>,
1919
initialState: TemplateFormState
20-
) => [initialState, '/action'],
20+
) => [initialState, '/yes-action'],
2121
};
2222
});
23+
jest.mock('@forms/DeleteTemplate/server-action', () => ({
24+
deleteTemplateYesAction: '/yes-action',
25+
deleteTemplateNoAction: '/no-action',
26+
}));
2327

2428
test('renders component correctly', () => {
2529
const container = render(

frontend/src/__tests__/components/forms/DeleteTemplate/__snapshots__/DeleteTemplate.test.tsx.snap

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,22 @@ exports[`renders component correctly 1`] = `
2222
The template will be removed and you won't be able to recover it.
2323
</p>
2424
<form
25-
action="/templates/manage-templates"
25+
action="/no-action"
2626
class="nhsuk-u-margin-right-3"
2727
style="display: inline;"
2828
>
29+
<input
30+
name="form-id"
31+
readonly=""
32+
type="hidden"
33+
value="delete-template-no"
34+
/>
35+
<input
36+
name="csrf_token"
37+
readonly=""
38+
type="hidden"
39+
value="no_token"
40+
/>
2941
<button
3042
aria-disabled="false"
3143
class="nhsuk-button nhsuk-button--secondary"
@@ -35,9 +47,21 @@ exports[`renders component correctly 1`] = `
3547
</button>
3648
</form>
3749
<form
38-
action="/action"
50+
action="/yes-action"
3951
style="display: inline;"
4052
>
53+
<input
54+
name="form-id"
55+
readonly=""
56+
type="hidden"
57+
value="delete-template-yes"
58+
/>
59+
<input
60+
name="csrf_token"
61+
readonly=""
62+
type="hidden"
63+
value="no_token"
64+
/>
4165
<button
4266
aria-disabled="false"
4367
class="nhsuk-button nhsuk-button--warning"

frontend/src/__tests__/components/forms/DeleteTemplate/server-action.test.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { redirect, RedirectType } from 'next/navigation';
2-
import { deleteTemplateAction } from '@forms/DeleteTemplate/server-action';
2+
import {
3+
deleteTemplateYesAction,
4+
deleteTemplateNoAction,
5+
} from '@forms/DeleteTemplate/server-action';
36
import {
47
NHSAppTemplate,
58
TemplateStatus,
@@ -15,6 +18,17 @@ beforeAll(() => {
1518
jest.setSystemTime(new Date('2022-01-01 09:00'));
1619
});
1720

21+
test('redirects', async () => {
22+
const mockRedirect = jest.mocked(redirect);
23+
24+
await deleteTemplateNoAction();
25+
26+
expect(mockRedirect).toHaveBeenCalledWith(
27+
'/manage-templates',
28+
RedirectType.push
29+
);
30+
});
31+
1832
test('calls form action and redirects', async () => {
1933
const mockRedirect = jest.mocked(redirect);
2034
const mockSaveTemplate = jest.mocked(saveTemplate);
@@ -27,7 +41,7 @@ test('calls form action and redirects', async () => {
2741
templateStatus: TemplateStatus.NOT_YET_SUBMITTED,
2842
};
2943

30-
await deleteTemplateAction(mockTemplate);
44+
await deleteTemplateYesAction(mockTemplate);
3145

3246
expect(mockSaveTemplate).toHaveBeenCalledWith({
3347
...mockTemplate,

frontend/src/__tests__/components/forms/EmailTemplateForm/__snapshots__/EmailTemplateForm.test.tsx.snap

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ exports[`renders page one error 1`] = `
7979
type="hidden"
8080
value="create-email-template"
8181
/>
82+
<input
83+
name="csrf_token"
84+
readonly=""
85+
type="hidden"
86+
value="no_token"
87+
/>
8288
<h1
8389
class="nhsuk-heading-xl"
8490
data-testid="page-heading"
@@ -693,6 +699,12 @@ exports[`renders page with multiple errors 1`] = `
693699
type="hidden"
694700
value="create-email-template"
695701
/>
702+
<input
703+
name="csrf_token"
704+
readonly=""
705+
type="hidden"
706+
value="no_token"
707+
/>
696708
<h1
697709
class="nhsuk-heading-xl"
698710
data-testid="page-heading"
@@ -1294,6 +1306,12 @@ exports[`renders page with preloaded field values 1`] = `
12941306
type="hidden"
12951307
value="create-email-template"
12961308
/>
1309+
<input
1310+
name="csrf_token"
1311+
readonly=""
1312+
type="hidden"
1313+
value="no_token"
1314+
/>
12971315
<h1
12981316
class="nhsuk-heading-xl"
12991317
data-testid="page-heading"
@@ -1835,6 +1853,12 @@ exports[`renders page without back link for initial state with id 1`] = `
18351853
type="hidden"
18361854
value="create-email-template"
18371855
/>
1856+
<input
1857+
name="csrf_token"
1858+
readonly=""
1859+
type="hidden"
1860+
value="no_token"
1861+
/>
18381862
<h1
18391863
class="nhsuk-heading-xl"
18401864
data-testid="page-heading"

frontend/src/__tests__/components/forms/NhsAppTemplateForm/__snapshots__/NhsAppTemplateForm.test.tsx.snap

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ exports[`renders page 1`] = `
4444
type="hidden"
4545
value="create-nhs-app-template"
4646
/>
47+
<input
48+
name="csrf_token"
49+
readonly=""
50+
type="hidden"
51+
value="no_token"
52+
/>
4753
<h1
4854
class="nhsuk-heading-xl"
4955
data-testid="page-heading"
@@ -524,6 +530,12 @@ exports[`renders page one error 1`] = `
524530
type="hidden"
525531
value="create-nhs-app-template"
526532
/>
533+
<input
534+
name="csrf_token"
535+
readonly=""
536+
type="hidden"
537+
value="no_token"
538+
/>
527539
<h1
528540
class="nhsuk-heading-xl"
529541
data-testid="page-heading"
@@ -1018,6 +1030,12 @@ exports[`renders page with multiple errors 1`] = `
10181030
type="hidden"
10191031
value="create-nhs-app-template"
10201032
/>
1033+
<input
1034+
name="csrf_token"
1035+
readonly=""
1036+
type="hidden"
1037+
value="no_token"
1038+
/>
10211039
<h1
10221040
class="nhsuk-heading-xl"
10231041
data-testid="page-heading"
@@ -1492,6 +1510,12 @@ exports[`renders page with preloaded field values 1`] = `
14921510
type="hidden"
14931511
value="create-nhs-app-template"
14941512
/>
1513+
<input
1514+
name="csrf_token"
1515+
readonly=""
1516+
type="hidden"
1517+
value="no_token"
1518+
/>
14951519
<h1
14961520
class="nhsuk-heading-xl"
14971521
data-testid="page-heading"
@@ -1920,6 +1944,12 @@ exports[`renders page without back link for initial state with id 1`] = `
19201944
type="hidden"
19211945
value="create-nhs-app-template"
19221946
/>
1947+
<input
1948+
name="csrf_token"
1949+
readonly=""
1950+
type="hidden"
1951+
value="no_token"
1952+
/>
19231953
<h1
19241954
class="nhsuk-heading-xl"
19251955
data-testid="page-heading"

frontend/src/__tests__/components/forms/ReviewEmailTemplate/__snapshots__/ReviewEmailTemplate.test.tsx.snap

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,12 @@ exports[`Review email form renders matches error snapshot 1`] = `
197197
type="hidden"
198198
value="review-email-template"
199199
/>
200+
<input
201+
name="csrf_token"
202+
readonly=""
203+
type="hidden"
204+
value="no_token"
205+
/>
200206
<div
201207
class="nhsuk-form-group nhsuk-form-group--error"
202208
>
@@ -465,6 +471,12 @@ exports[`Review email form renders matches snapshot when navigating from edit sc
465471
type="hidden"
466472
value="review-email-template"
467473
/>
474+
<input
475+
name="csrf_token"
476+
readonly=""
477+
type="hidden"
478+
value="no_token"
479+
/>
468480
<div
469481
class="nhsuk-form-group"
470482
>
@@ -716,6 +728,12 @@ exports[`Review email form renders matches snapshot when navigating from manage
716728
type="hidden"
717729
value="review-email-template"
718730
/>
731+
<input
732+
name="csrf_token"
733+
readonly=""
734+
type="hidden"
735+
value="no_token"
736+
/>
719737
<div
720738
class="nhsuk-form-group"
721739
>

0 commit comments

Comments
 (0)