Skip to content

Commit 2e4e09e

Browse files
authored
fix: handle when header is an array (#3)
1 parent a05657e commit 2e4e09e

File tree

3 files changed

+95
-4
lines changed

3 files changed

+95
-4
lines changed

readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ const httpValidator = new HttpValidator({
7272
)
7373
}
7474
],
75+
tokenMandatory: true // Optional (default: true)
7576
issuer: 'eyevinn',
7677
audience: ['one', 'two'] // Optional
7778
});

src/validators/http.test.ts

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { createRequest } from 'node-mocks-http';
2-
import { HttpValidator } from './http';
2+
import { HttpValidator, NoTokenFoundError } from './http';
33
import { CAT } from '..';
44

55
describe('HTTP Request CAT Validator', () => {
@@ -127,4 +127,65 @@ describe('HTTP Request CAT Validator', () => {
127127
const result = await httpValidator.validateHttpRequest(request);
128128
expect(result.status).toBe(200);
129129
});
130+
131+
test('can handle when CTA access token header is an array', async () => {
132+
const request = createRequest({
133+
method: 'GET',
134+
headers: {
135+
'CTA-Common-Access-Token': [
136+
'2D3RhEOhAQWhBFBha2FtYWlfa2V5X2hzMjU2U6MEGnUCOrsGGmfXRKwFGmfXRKxYIOM6yRx830uqAamWFv1amFYRa5vaV2z5lIQTqFEvFh8z'
137+
]
138+
}
139+
});
140+
const httpValidator = new HttpValidator({
141+
keys: [
142+
{
143+
kid: 'Symmetric256',
144+
key: Buffer.from(
145+
'403697de87af64611c1d32a05dab0fe1fcb715a86ab435f1ec99192d79569388',
146+
'hex'
147+
)
148+
}
149+
],
150+
issuer: 'eyevinn'
151+
});
152+
const result = await httpValidator.validateHttpRequest(request);
153+
expect(result.status).toBe(200);
154+
});
155+
156+
test('returns ok when CTA common access token is optional', async () => {
157+
const request = createRequest({
158+
method: 'GET'
159+
});
160+
const httpValidator = new HttpValidator({
161+
keys: [
162+
{
163+
kid: 'Symmetric256',
164+
key: Buffer.from(
165+
'403697de87af64611c1d32a05dab0fe1fcb715a86ab435f1ec99192d79569388',
166+
'hex'
167+
)
168+
}
169+
],
170+
issuer: 'eyevinn'
171+
});
172+
await expect(httpValidator.validateHttpRequest(request)).rejects.toThrow(
173+
NoTokenFoundError
174+
);
175+
const httpValidatorOptional = new HttpValidator({
176+
keys: [
177+
{
178+
kid: 'Symmetric256',
179+
key: Buffer.from(
180+
'403697de87af64611c1d32a05dab0fe1fcb715a86ab435f1ec99192d79569388',
181+
'hex'
182+
)
183+
}
184+
],
185+
issuer: 'eyevinn',
186+
tokenMandatory: false
187+
});
188+
const result = await httpValidatorOptional.validateHttpRequest(request);
189+
expect(result.status).toBe(200);
190+
});
130191
});

src/validators/http.ts

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
import { IncomingMessage } from 'node:http';
22
import { CAT } from '..';
3+
import {
4+
InvalidAudienceError,
5+
InvalidIssuerError,
6+
KeyNotFoundError,
7+
TokenExpiredError
8+
} from '../errors';
39

410
interface HttpValidatorKey {
511
kid: string;
612
key: Buffer;
713
}
814

915
export interface HttpValidatorOptions {
16+
tokenMandatory?: boolean;
1017
keys: HttpValidatorKey[];
1118
issuer: string;
1219
audience?: string[];
@@ -17,6 +24,12 @@ export interface HttpResponse {
1724
message?: string;
1825
}
1926

27+
export class NoTokenFoundError extends Error {
28+
constructor() {
29+
super('No CTA token could be found');
30+
}
31+
}
32+
2033
/**
2134
* Handle request and validate CTA Common Access Token
2235
*
@@ -49,6 +62,7 @@ export class HttpValidator {
4962
this.keys[k.kid] = k.key;
5063
});
5164
this.opts = opts;
65+
this.opts.tokenMandatory = opts.tokenMandatory ?? true;
5266
}
5367

5468
public async validateHttpRequest(
@@ -60,17 +74,32 @@ export class HttpValidator {
6074

6175
// Check for token in headers first
6276
if (request.headers['cta-common-access-token']) {
63-
const token = request.headers['cta-common-access-token'] as string;
77+
const token = Array.isArray(request.headers['cta-common-access-token'])
78+
? request.headers['cta-common-access-token'][0]
79+
: request.headers['cta-common-access-token'];
6480
try {
6581
await validator.validate(token, 'mac', {
6682
issuer: this.opts.issuer,
6783
audience: this.opts.audience
6884
});
6985
return { status: 200 };
7086
} catch (err) {
71-
return { status: 401, message: (err as Error).message };
87+
if (
88+
err instanceof InvalidIssuerError ||
89+
err instanceof InvalidAudienceError ||
90+
err instanceof KeyNotFoundError ||
91+
err instanceof TokenExpiredError
92+
) {
93+
return { status: 401, message: (err as Error).message };
94+
} else {
95+
console.log(`Internal error`, err);
96+
return { status: 500, message: (err as Error).message };
97+
}
7298
}
7399
}
74-
throw new Error('No CTA token could be found');
100+
if (this.opts.tokenMandatory) {
101+
throw new NoTokenFoundError();
102+
}
103+
return { status: 200 };
75104
}
76105
}

0 commit comments

Comments
 (0)