Skip to content

Commit 7d81c08

Browse files
committed
unhappy path unit tests
1 parent 6d1fb55 commit 7d81c08

File tree

2 files changed

+74
-14
lines changed

2 files changed

+74
-14
lines changed

lambdas/download-authorizer/src/__tests__/index.test.ts

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import type { CloudFrontRequestEvent } from 'aws-lambda';
1+
import type { CloudFrontRequest, CloudFrontRequestEvent } from 'aws-lambda';
22
import { mock } from 'jest-mock-extended';
33
import { logger } from 'nhs-notify-web-template-management-utils/logger';
4-
import { handler } from '../index';
4+
import { denial, handler, parseRequest } from '../index';
55
import { LambdaCognitoAuthorizer } from 'nhs-notify-web-template-management-utils/lambda-cognito-authorizer';
66
import { CognitoIdentityProviderClient } from '@aws-sdk/client-cognito-identity-provider';
77

@@ -85,4 +85,72 @@ describe('download authorizer handler', () => {
8585
subject
8686
);
8787
});
88+
89+
test('returns denial if cognito configuration is not present in custom headers', async () => {
90+
const uri = '/subject/template-id/proof1.pdf';
91+
const cookie =
92+
'CognitoIdentityServiceProvider.user-pool-client-id.subject.AccessToken=jwt';
93+
94+
const event = mock<CloudFrontRequestEvent>(
95+
makeEvent(uri, cookie, {
96+
'x-user-pool-id': undefined,
97+
'x-user-pool-client-id': undefined,
98+
})
99+
);
100+
101+
const res = await handler(event);
102+
103+
expect(res).toEqual(denial);
104+
expect(mockLogger.error).toHaveBeenCalledWith('Lambda misconfiguration');
105+
106+
expect(lambdaCognitoAuthorizer.authorize).not.toHaveBeenCalled();
107+
});
108+
109+
test('returns denial if required cookie is not available', async () => {
110+
const uri = '/subject/template-id/proof1.pdf';
111+
const cookie = 'k=v; k2=v2';
112+
113+
const event = mock<CloudFrontRequestEvent>(makeEvent(uri, cookie));
114+
115+
const res = await handler(event);
116+
117+
expect(res).toEqual(denial);
118+
expect(mockLogger.warn).toHaveBeenCalledWith('Cookie is missing');
119+
120+
expect(lambdaCognitoAuthorizer.authorize).not.toHaveBeenCalled();
121+
});
122+
123+
test('returns denial if authorization fails', async () => {
124+
const uri = '/subject/template-id/proof1.pdf';
125+
const cookie = `CognitoIdentityServiceProvider.${userPoolClientId}.subject.AccessToken=jwt`;
126+
127+
lambdaCognitoAuthorizer.authorize.mockResolvedValue({
128+
success: false,
129+
});
130+
131+
const event = mock<CloudFrontRequestEvent>(makeEvent(uri, cookie));
132+
133+
const res = await handler(event);
134+
135+
expect(res).toEqual(denial);
136+
});
137+
});
138+
139+
describe('parseRequest', () => {
140+
test('path defaults to empty string if owner segment cant be extracted', () => {
141+
const uri = '';
142+
const request = mock<CloudFrontRequest>(
143+
makeEvent(uri, 'cookie').Records[0].cf.request
144+
);
145+
146+
expect(parseRequest(request).ownerPathComponent).toBe('');
147+
});
148+
149+
test('cookie header defaults to empty string if it is not present on request', () => {
150+
const request = mock<CloudFrontRequest>(
151+
makeEvent('/subject/file.txt', undefined).Records[0].cf.request
152+
);
153+
154+
expect(parseRequest(request).authorizationToken).toBe(undefined);
155+
});
88156
});

lambdas/download-authorizer/src/index.ts

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ const cognitoClient = new CognitoIdentityProviderClient({
88
region: 'eu-west-2',
99
});
1010

11-
const denial = {
11+
export const denial = {
1212
status: '403',
1313
statusDescription: 'Forbidden',
1414
body: '<h1>Access Denied</h1>',
1515
};
1616

17-
function parseRequest(request: CloudFrontRequest) {
18-
const [, ownerPathComponent] = request.uri.split('/');
17+
export function parseRequest(request: CloudFrontRequest) {
18+
const ownerPathComponent = request.uri.split('/')[1] ?? '';
1919

2020
const customHeaders = request.origin?.s3?.customHeaders;
2121
const userPoolId = customHeaders?.['x-user-pool-id']?.[0]?.value;
@@ -35,7 +35,6 @@ function parseRequest(request: CloudFrontRequest) {
3535
}
3636

3737
export const handler = async (event: CloudFrontRequestEvent) => {
38-
logger.info(event);
3938
const { request } = event.Records[0].cf;
4039

4140
const {
@@ -55,11 +54,6 @@ export const handler = async (event: CloudFrontRequestEvent) => {
5554
return denial;
5655
}
5756

58-
if (!ownerPathComponent) {
59-
logger.warn('Could not determine expected subject');
60-
return denial;
61-
}
62-
6357
const authorizer = new LambdaCognitoAuthorizer(cognitoClient, logger);
6458

6559
const authResult = await authorizer.authorize(
@@ -69,9 +63,7 @@ export const handler = async (event: CloudFrontRequestEvent) => {
6963
ownerPathComponent
7064
);
7165

72-
if (authResult.success) {
73-
return request;
74-
}
66+
if (authResult.success) return request;
7567

7668
return denial;
7769
};

0 commit comments

Comments
 (0)