client-certificate-auth 1.2.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/extractor.cjs +20 -0
- package/lib/extractor.d.cts +13 -0
- package/lib/helpers.cjs +20 -0
- package/lib/helpers.d.cts +13 -0
- package/lib/helpers.d.ts +2 -6
- package/lib/helpers.js +18 -7
- package/lib/parsers.cjs +20 -0
- package/lib/parsers.d.cts +13 -0
- package/package.json +27 -2
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* client-certificate-auth/extractor - CommonJS wrapper
|
|
3
|
+
* Copyright (C) 2013-2026 Tony Gies
|
|
4
|
+
* @license MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
let _module;
|
|
10
|
+
|
|
11
|
+
async function load() {
|
|
12
|
+
// Stryker disable next-line ConditionalExpression,BlockStatement: test ordering caches _module from prior test; ConditionalExpression→true (always re-import) re-imports same module successfully; BlockStatement→{} uses cached value
|
|
13
|
+
if (!_module) {
|
|
14
|
+
// Stryker disable next-line StringLiteral: test ordering caches _module; StringLiteral→"" fails import but cached value masks it
|
|
15
|
+
_module = await import('./extractor.js');
|
|
16
|
+
}
|
|
17
|
+
return _module;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
module.exports = { load };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* client-certificate-auth/extractor - CommonJS type declarations
|
|
3
|
+
* Copyright (C) 2013-2026 Tony Gies
|
|
4
|
+
* @license MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type * as ExtractorModule from './extractor.js';
|
|
8
|
+
|
|
9
|
+
declare const extractor: {
|
|
10
|
+
load(): Promise<typeof ExtractorModule>;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export = extractor;
|
package/lib/helpers.cjs
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* client-certificate-auth/helpers - CommonJS wrapper
|
|
3
|
+
* Copyright (C) 2013-2026 Tony Gies
|
|
4
|
+
* @license MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
let _module;
|
|
10
|
+
|
|
11
|
+
async function load() {
|
|
12
|
+
// Stryker disable next-line ConditionalExpression,BlockStatement: test ordering caches _module from prior test; ConditionalExpression→true (always re-import) re-imports same module successfully; BlockStatement→{} uses cached value
|
|
13
|
+
if (!_module) {
|
|
14
|
+
// Stryker disable next-line StringLiteral: test ordering caches _module; StringLiteral→"" fails import but cached value masks it
|
|
15
|
+
_module = await import('./helpers.js');
|
|
16
|
+
}
|
|
17
|
+
return _module;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
module.exports = { load };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* client-certificate-auth/helpers - CommonJS type declarations
|
|
3
|
+
* Copyright (C) 2013-2026 Tony Gies
|
|
4
|
+
* @license MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type * as HelpersModule from './helpers.js';
|
|
8
|
+
|
|
9
|
+
declare const helpers: {
|
|
10
|
+
load(): Promise<typeof HelpersModule>;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export = helpers;
|
package/lib/helpers.d.ts
CHANGED
|
@@ -4,13 +4,9 @@
|
|
|
4
4
|
* @license MIT
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type {
|
|
8
|
-
import type { ClientCertRequest } from './clientCertificateAuth.js';
|
|
7
|
+
import type { ValidationCallback } from './clientCertificateAuth.js';
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
* Validation callback for clientCertificateAuth middleware.
|
|
12
|
-
*/
|
|
13
|
-
export type ValidationCallback = (cert: PeerCertificate | DetailedPeerCertificate, req?: ClientCertRequest) => boolean | Promise<boolean>;
|
|
9
|
+
export type { ValidationCallback };
|
|
14
10
|
|
|
15
11
|
/**
|
|
16
12
|
* Distinguished Name fields for matching.
|
package/lib/helpers.js
CHANGED
|
@@ -9,6 +9,17 @@
|
|
|
9
9
|
* @typedef {(cert: PeerCertificate, req?: import('http').IncomingMessage) => boolean | Promise<boolean>} ValidationCallback
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Normalize a certificate DN field value to an array.
|
|
14
|
+
* Node.js returns string for single-valued and string[] for multi-valued DN attributes.
|
|
15
|
+
* @param {string | string[] | undefined} value
|
|
16
|
+
* @returns {string[]}
|
|
17
|
+
*/
|
|
18
|
+
function toArray(value) {
|
|
19
|
+
if (value === undefined || value === null) {return [];}
|
|
20
|
+
return Array.isArray(value) ? value : [value];
|
|
21
|
+
}
|
|
22
|
+
|
|
12
23
|
/**
|
|
13
24
|
* Create a validation callback that allows certificates with matching Common Names.
|
|
14
25
|
*
|
|
@@ -20,7 +31,7 @@
|
|
|
20
31
|
*/
|
|
21
32
|
export function allowCN(names) {
|
|
22
33
|
const allowed = new Set(names);
|
|
23
|
-
return (cert) =>
|
|
34
|
+
return (cert) => toArray(cert.subject?.CN).some((cn) => allowed.has(cn));
|
|
24
35
|
}
|
|
25
36
|
|
|
26
37
|
/**
|
|
@@ -76,7 +87,7 @@ export function allowIssuer(match) {
|
|
|
76
87
|
const entries = Object.entries(match);
|
|
77
88
|
return (cert) => {
|
|
78
89
|
if (!cert.issuer) {return false;}
|
|
79
|
-
return entries.every(([key, value]) => cert.issuer[key]
|
|
90
|
+
return entries.every(([key, value]) => toArray(cert.issuer[key]).includes(value));
|
|
80
91
|
};
|
|
81
92
|
}
|
|
82
93
|
|
|
@@ -94,7 +105,7 @@ export function allowSubject(match) {
|
|
|
94
105
|
const entries = Object.entries(match);
|
|
95
106
|
return (cert) => {
|
|
96
107
|
if (!cert.subject) {return false;}
|
|
97
|
-
return entries.every(([key, value]) => cert.subject[key]
|
|
108
|
+
return entries.every(([key, value]) => toArray(cert.subject[key]).includes(value));
|
|
98
109
|
};
|
|
99
110
|
}
|
|
100
111
|
|
|
@@ -109,7 +120,7 @@ export function allowSubject(match) {
|
|
|
109
120
|
*/
|
|
110
121
|
export function allowOU(ous) {
|
|
111
122
|
const allowed = new Set(ous);
|
|
112
|
-
return (cert) =>
|
|
123
|
+
return (cert) => toArray(cert.subject?.OU).some((ou) => allowed.has(ou));
|
|
113
124
|
}
|
|
114
125
|
|
|
115
126
|
/**
|
|
@@ -123,7 +134,7 @@ export function allowOU(ous) {
|
|
|
123
134
|
*/
|
|
124
135
|
export function allowOrganization(orgs) {
|
|
125
136
|
const allowed = new Set(orgs);
|
|
126
|
-
return (cert) =>
|
|
137
|
+
return (cert) => toArray(cert.subject?.O).some((o) => allowed.has(o));
|
|
127
138
|
}
|
|
128
139
|
|
|
129
140
|
/**
|
|
@@ -196,9 +207,9 @@ export function allowEmail(emails) {
|
|
|
196
207
|
const allowed = new Set(emails.map((e) => e.toLowerCase()));
|
|
197
208
|
|
|
198
209
|
return (cert) => {
|
|
199
|
-
// Check subject.emailAddress
|
|
210
|
+
// Check subject.emailAddress (may be string or string[] for multi-valued)
|
|
200
211
|
if (cert.subject?.emailAddress) {
|
|
201
|
-
if (
|
|
212
|
+
if (toArray(cert.subject.emailAddress).some((e) => allowed.has(e.toLowerCase()))) {
|
|
202
213
|
return true;
|
|
203
214
|
}
|
|
204
215
|
}
|
package/lib/parsers.cjs
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* client-certificate-auth/parsers - CommonJS wrapper
|
|
3
|
+
* Copyright (C) 2013-2026 Tony Gies
|
|
4
|
+
* @license MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
let _module;
|
|
10
|
+
|
|
11
|
+
async function load() {
|
|
12
|
+
// Stryker disable next-line ConditionalExpression,BlockStatement: test ordering caches _module from prior test; ConditionalExpression→true (always re-import) re-imports same module successfully; BlockStatement→{} uses cached value
|
|
13
|
+
if (!_module) {
|
|
14
|
+
// Stryker disable next-line StringLiteral: test ordering caches _module; StringLiteral→"" fails import but cached value masks it
|
|
15
|
+
_module = await import('./parsers.js');
|
|
16
|
+
}
|
|
17
|
+
return _module;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
module.exports = { load };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* client-certificate-auth/parsers - CommonJS type declarations
|
|
3
|
+
* Copyright (C) 2013-2026 Tony Gies
|
|
4
|
+
* @license MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type * as ParsersModule from './parsers.js';
|
|
8
|
+
|
|
9
|
+
declare const parsers: {
|
|
10
|
+
load(): Promise<typeof ParsersModule>;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export = parsers;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "client-certificate-auth",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Express/Connect middleware for mTLS client certificate authentication with reverse proxy support (AWS ALB, Envoy, Cloudflare, Traefik)",
|
|
5
5
|
"homepage": "https://github.com/tgies/client-certificate-auth",
|
|
6
6
|
"bugs": {
|
|
@@ -26,23 +26,48 @@
|
|
|
26
26
|
"import": {
|
|
27
27
|
"types": "./lib/parsers.d.ts",
|
|
28
28
|
"default": "./lib/parsers.js"
|
|
29
|
+
},
|
|
30
|
+
"require": {
|
|
31
|
+
"types": "./lib/parsers.d.cts",
|
|
32
|
+
"default": "./lib/parsers.cjs"
|
|
29
33
|
}
|
|
30
34
|
},
|
|
31
35
|
"./helpers": {
|
|
32
36
|
"import": {
|
|
33
37
|
"types": "./lib/helpers.d.ts",
|
|
34
38
|
"default": "./lib/helpers.js"
|
|
39
|
+
},
|
|
40
|
+
"require": {
|
|
41
|
+
"types": "./lib/helpers.d.cts",
|
|
42
|
+
"default": "./lib/helpers.cjs"
|
|
35
43
|
}
|
|
36
44
|
},
|
|
37
45
|
"./extractor": {
|
|
38
46
|
"import": {
|
|
39
47
|
"types": "./lib/extractor.d.ts",
|
|
40
48
|
"default": "./lib/extractor.js"
|
|
49
|
+
},
|
|
50
|
+
"require": {
|
|
51
|
+
"types": "./lib/extractor.d.cts",
|
|
52
|
+
"default": "./lib/extractor.cjs"
|
|
41
53
|
}
|
|
42
54
|
}
|
|
43
55
|
},
|
|
44
56
|
"main": "./lib/clientCertificateAuth.cjs",
|
|
45
57
|
"types": "./lib/clientCertificateAuth.d.ts",
|
|
58
|
+
"typesVersions": {
|
|
59
|
+
"*": {
|
|
60
|
+
"parsers": [
|
|
61
|
+
"./lib/parsers.d.ts"
|
|
62
|
+
],
|
|
63
|
+
"helpers": [
|
|
64
|
+
"./lib/helpers.d.ts"
|
|
65
|
+
],
|
|
66
|
+
"extractor": [
|
|
67
|
+
"./lib/extractor.d.ts"
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
},
|
|
46
71
|
"engines": {
|
|
47
72
|
"node": ">= 20"
|
|
48
73
|
},
|
|
@@ -52,7 +77,7 @@
|
|
|
52
77
|
"@stryker-mutator/core": "^9.5.1",
|
|
53
78
|
"@stryker-mutator/jest-runner": "^9.5.1",
|
|
54
79
|
"@types/express": "^5.0.6",
|
|
55
|
-
"@types/node": "^25.2.
|
|
80
|
+
"@types/node": "^25.2.3",
|
|
56
81
|
"c8": "^10.1.3",
|
|
57
82
|
"eslint": "^9.17.0",
|
|
58
83
|
"globals": "^17.3.0",
|