Skip to content

Commit 000b48c

Browse files
committed
chore: improve self signed tls cert checks
Ticket: WP-6407
1 parent 43985a8 commit 000b48c

File tree

2 files changed

+95
-3
lines changed

2 files changed

+95
-3
lines changed

src/__tests__/appUtils.test.ts

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,5 +182,92 @@ describe('appUtils', () => {
182182
mockRes.statusCode.should.equal(0); // No rejection when TLS is disabled
183183
});
184184
});
185+
186+
describe('Self-signed certificate checks', () => {
187+
it('should reject self-signed certificate when not allowed (all fields match)', () => {
188+
const middleware = createMtlsMiddleware({
189+
tlsMode: TlsMode.MTLS,
190+
clientCertAllowSelfSigned: false,
191+
mtlsAllowedClientFingerprints: ['ABCDEF1234567890ABCDEF1234567890'],
192+
});
193+
194+
const mockReq = {
195+
socket: {
196+
getPeerCertificate: () => ({
197+
subject: { CN: 'test-client', O: 'Test Org', OU: 'Test Unit' },
198+
issuer: { CN: 'test-client', O: 'Test Org', OU: 'Test Unit' },
199+
fingerprint256: 'AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90',
200+
}),
201+
},
202+
} as any;
203+
204+
const mockRes = {
205+
status: function (code: number) {
206+
this.statusCode = code;
207+
return this;
208+
},
209+
json: function (body: any) {
210+
this.body = body;
211+
return this;
212+
},
213+
statusCode: 0,
214+
body: {},
215+
} as any;
216+
217+
let nextCalled = false;
218+
const mockNext = () => {
219+
nextCalled = true;
220+
};
221+
222+
middleware(mockReq, mockRes, mockNext);
223+
224+
nextCalled.should.be.false();
225+
mockRes.statusCode.should.equal(403);
226+
mockRes.body.should.have.property('error', 'mTLS Authentication Failed');
227+
mockRes.body.should.have.property('message', 'Self-signed certificates are not allowed');
228+
mockRes.body.should.have.property('details').match(/CLIENT_CERT_ALLOW_SELF_SIGNED=true/);
229+
});
230+
231+
it('should accept self-signed certificate when allowed', () => {
232+
const middleware = createMtlsMiddleware({
233+
tlsMode: TlsMode.MTLS,
234+
clientCertAllowSelfSigned: true,
235+
mtlsAllowedClientFingerprints: ['ABCDEF1234567890ABCDEF1234567890'],
236+
});
237+
238+
const mockReq = {
239+
socket: {
240+
getPeerCertificate: () => ({
241+
subject: { CN: 'test-client', O: 'Test Org', OU: 'Test Unit' },
242+
issuer: { CN: 'test-client', O: 'Test Org', OU: 'Test Unit' },
243+
fingerprint256: 'AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90',
244+
}),
245+
},
246+
} as any;
247+
248+
const mockRes = {
249+
status: function (code: number) {
250+
this.statusCode = code;
251+
return this;
252+
},
253+
json: function (body: any) {
254+
this.body = body;
255+
return this;
256+
},
257+
statusCode: 0,
258+
body: {},
259+
} as any;
260+
261+
let nextCalled = false;
262+
const mockNext = () => {
263+
nextCalled = true;
264+
};
265+
266+
middleware(mockReq, mockRes, mockNext);
267+
268+
nextCalled.should.be.true();
269+
mockRes.statusCode.should.equal(0);
270+
});
271+
});
185272
});
186273
});

src/shared/appUtils.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,17 @@ export function createMtlsMiddleware(config: {
160160
}
161161
}
162162

163-
// Check if self-signed certificates are allowed
164-
if (!config.clientCertAllowSelfSigned && clientCert.issuer.CN === clientCert.subject.CN) {
163+
const isSelfSigned =
164+
clientCert.issuer.CN === clientCert.subject.CN &&
165+
clientCert.issuer.O === clientCert.subject.O &&
166+
clientCert.issuer.OU === clientCert.subject.OU;
167+
168+
if (!config.clientCertAllowSelfSigned && isSelfSigned) {
165169
return res.status(403).json({
166170
error: 'mTLS Authentication Failed',
167171
message: 'Self-signed certificates are not allowed',
168-
details: 'Please use a certificate issued by a trusted CA',
172+
details:
173+
'Please use a certificate issued by a trusted CA, or set CLIENT_CERT_ALLOW_SELF_SIGNED=true for testing',
169174
});
170175
}
171176

0 commit comments

Comments
 (0)