@naylence/runtime 0.3.16 → 0.3.17
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/dist/browser/index.cjs +50 -2
- package/dist/browser/index.mjs +50 -2
- package/dist/cjs/naylence/fame/security/auth/oauth2-authorizer-factory.js +7 -0
- package/dist/cjs/naylence/fame/security/auth/oauth2-authorizer.js +41 -0
- package/dist/cjs/version.js +2 -2
- package/dist/esm/naylence/fame/security/auth/oauth2-authorizer-factory.js +7 -0
- package/dist/esm/naylence/fame/security/auth/oauth2-authorizer.js +42 -1
- package/dist/esm/version.js +2 -2
- package/dist/node/index.cjs +50 -2
- package/dist/node/index.mjs +50 -2
- package/dist/node/node.cjs +50 -2
- package/dist/node/node.mjs +50 -2
- package/dist/types/naylence/fame/security/auth/oauth2-authorizer-factory.d.ts +2 -0
- package/dist/types/naylence/fame/security/auth/oauth2-authorizer.d.ts +3 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/browser/index.cjs
CHANGED
|
@@ -515,12 +515,12 @@ async function ensureRuntimeFactoriesRegistered(registry = factory.Registry) {
|
|
|
515
515
|
}
|
|
516
516
|
|
|
517
517
|
// This file is auto-generated during build - do not edit manually
|
|
518
|
-
// Generated from package.json version: 0.3.
|
|
518
|
+
// Generated from package.json version: 0.3.17
|
|
519
519
|
/**
|
|
520
520
|
* The package version, injected at build time.
|
|
521
521
|
* @internal
|
|
522
522
|
*/
|
|
523
|
-
const VERSION = '0.3.
|
|
523
|
+
const VERSION = '0.3.17';
|
|
524
524
|
|
|
525
525
|
let initialized = false;
|
|
526
526
|
const runtimePlugin = {
|
|
@@ -34710,6 +34710,7 @@ class OAuth2AuthorizerFactory extends AuthorizerFactory {
|
|
|
34710
34710
|
defaultTtlSec: normalized.defaultTtlSec,
|
|
34711
34711
|
maxTtlSec: normalized.maxTtlSec,
|
|
34712
34712
|
reverseAuthTtlSec: normalized.reverseAuthTtlSec,
|
|
34713
|
+
enforceTokenSubjectNodeIdentity: normalized.enforceTokenSubjectNodeIdentity,
|
|
34713
34714
|
};
|
|
34714
34715
|
if (tokenIssuer) {
|
|
34715
34716
|
authorizerOptions.tokenIssuer = tokenIssuer;
|
|
@@ -34777,6 +34778,11 @@ function normalizeConfig$c(config) {
|
|
|
34777
34778
|
: typeof source.reverse_auth_ttl_sec === 'number'
|
|
34778
34779
|
? source.reverse_auth_ttl_sec
|
|
34779
34780
|
: DEFAULT_REVERSE_AUTH_TTL_SEC;
|
|
34781
|
+
const enforceTokenSubjectNodeIdentity = typeof source.enforceTokenSubjectNodeIdentity === 'boolean'
|
|
34782
|
+
? source.enforceTokenSubjectNodeIdentity
|
|
34783
|
+
: typeof source.enforce_token_subject_node_identity === 'boolean'
|
|
34784
|
+
? source.enforce_token_subject_node_identity
|
|
34785
|
+
: false;
|
|
34780
34786
|
const tokenVerifierConfigInput = source.tokenVerifierConfig ?? source.token_verifier_config ?? null;
|
|
34781
34787
|
const tokenVerifierConfig = normalizeTokenVerifierConfig({
|
|
34782
34788
|
config: tokenVerifierConfigInput,
|
|
@@ -34795,6 +34801,7 @@ function normalizeConfig$c(config) {
|
|
|
34795
34801
|
maxTtlSec,
|
|
34796
34802
|
tokenVerifierConfig,
|
|
34797
34803
|
reverseAuthTtlSec: reverseAuthCandidate,
|
|
34804
|
+
enforceTokenSubjectNodeIdentity,
|
|
34798
34805
|
...(audience ? { audience } : {}),
|
|
34799
34806
|
};
|
|
34800
34807
|
if (tokenIssuerConfig) {
|
|
@@ -39832,6 +39839,10 @@ function normalizeOptions$4(raw) {
|
|
|
39832
39839
|
: typeof snake.aud === 'string'
|
|
39833
39840
|
? snake.aud
|
|
39834
39841
|
: undefined);
|
|
39842
|
+
const enforceTokenSubjectNodeIdentity = camel.enforceTokenSubjectNodeIdentity ??
|
|
39843
|
+
(typeof snake.enforce_token_subject_node_identity === 'boolean'
|
|
39844
|
+
? snake.enforce_token_subject_node_identity
|
|
39845
|
+
: undefined);
|
|
39835
39846
|
return {
|
|
39836
39847
|
tokenVerifier,
|
|
39837
39848
|
tokenIssuer,
|
|
@@ -39841,6 +39852,7 @@ function normalizeOptions$4(raw) {
|
|
|
39841
39852
|
defaultTtlSec,
|
|
39842
39853
|
maxTtlSec,
|
|
39843
39854
|
reverseAuthTtlSec,
|
|
39855
|
+
enforceTokenSubjectNodeIdentity,
|
|
39844
39856
|
};
|
|
39845
39857
|
}
|
|
39846
39858
|
class OAuth2Authorizer {
|
|
@@ -39854,6 +39866,8 @@ class OAuth2Authorizer {
|
|
|
39854
39866
|
this.requireScope = options.requireScope ?? true;
|
|
39855
39867
|
this.reverseAuthTtlSec =
|
|
39856
39868
|
options.reverseAuthTtlSec ?? DEFAULT_REVERSE_AUTH_TTL_SEC;
|
|
39869
|
+
this.enforceTokenSubjectNodeIdentity =
|
|
39870
|
+
options.enforceTokenSubjectNodeIdentity ?? false;
|
|
39857
39871
|
}
|
|
39858
39872
|
get tokenVerifier() {
|
|
39859
39873
|
return this.tokenVerifierImpl;
|
|
@@ -39983,6 +39997,13 @@ class OAuth2Authorizer {
|
|
|
39983
39997
|
});
|
|
39984
39998
|
return undefined;
|
|
39985
39999
|
}
|
|
40000
|
+
// Enforce token subject node identity if enabled
|
|
40001
|
+
if (this.enforceTokenSubjectNodeIdentity) {
|
|
40002
|
+
const validationResult = await this.validateTokenSubjectNodeIdentity(frame.systemId, claims);
|
|
40003
|
+
if (!validationResult) {
|
|
40004
|
+
return undefined;
|
|
40005
|
+
}
|
|
40006
|
+
}
|
|
39986
40007
|
claims.instance_id = claims.instance_id ?? frame.instanceId;
|
|
39987
40008
|
claims.assigned_path = claims.assigned_path ?? frame.assignedPath;
|
|
39988
40009
|
claims.accepted_capabilities =
|
|
@@ -40060,6 +40081,33 @@ class OAuth2Authorizer {
|
|
|
40060
40081
|
}
|
|
40061
40082
|
return false;
|
|
40062
40083
|
}
|
|
40084
|
+
async validateTokenSubjectNodeIdentity(systemId, claims) {
|
|
40085
|
+
const sub = claims.sub;
|
|
40086
|
+
if (typeof sub !== 'string' || sub.trim().length === 0) {
|
|
40087
|
+
logger$3.warning('oauth2_attach_missing_subject_claim', {
|
|
40088
|
+
system_id: systemId,
|
|
40089
|
+
});
|
|
40090
|
+
return false;
|
|
40091
|
+
}
|
|
40092
|
+
const expectedPrefix = await core.generateIdAsync({
|
|
40093
|
+
mode: 'fingerprint',
|
|
40094
|
+
material: sub,
|
|
40095
|
+
length: 8,
|
|
40096
|
+
});
|
|
40097
|
+
if (!systemId.startsWith(`${expectedPrefix}-`)) {
|
|
40098
|
+
logger$3.warning('oauth2_attach_node_identity_mismatch', {
|
|
40099
|
+
system_id: systemId,
|
|
40100
|
+
expected_prefix: expectedPrefix,
|
|
40101
|
+
subject: sub,
|
|
40102
|
+
});
|
|
40103
|
+
return false;
|
|
40104
|
+
}
|
|
40105
|
+
logger$3.debug('oauth2_attach_node_identity_verified', {
|
|
40106
|
+
system_id: systemId,
|
|
40107
|
+
expected_prefix: expectedPrefix,
|
|
40108
|
+
});
|
|
40109
|
+
return true;
|
|
40110
|
+
}
|
|
40063
40111
|
}
|
|
40064
40112
|
|
|
40065
40113
|
var oauth2Authorizer = /*#__PURE__*/Object.freeze({
|
package/dist/browser/index.mjs
CHANGED
|
@@ -513,12 +513,12 @@ async function ensureRuntimeFactoriesRegistered(registry = Registry) {
|
|
|
513
513
|
}
|
|
514
514
|
|
|
515
515
|
// This file is auto-generated during build - do not edit manually
|
|
516
|
-
// Generated from package.json version: 0.3.
|
|
516
|
+
// Generated from package.json version: 0.3.17
|
|
517
517
|
/**
|
|
518
518
|
* The package version, injected at build time.
|
|
519
519
|
* @internal
|
|
520
520
|
*/
|
|
521
|
-
const VERSION = '0.3.
|
|
521
|
+
const VERSION = '0.3.17';
|
|
522
522
|
|
|
523
523
|
let initialized = false;
|
|
524
524
|
const runtimePlugin = {
|
|
@@ -34708,6 +34708,7 @@ class OAuth2AuthorizerFactory extends AuthorizerFactory {
|
|
|
34708
34708
|
defaultTtlSec: normalized.defaultTtlSec,
|
|
34709
34709
|
maxTtlSec: normalized.maxTtlSec,
|
|
34710
34710
|
reverseAuthTtlSec: normalized.reverseAuthTtlSec,
|
|
34711
|
+
enforceTokenSubjectNodeIdentity: normalized.enforceTokenSubjectNodeIdentity,
|
|
34711
34712
|
};
|
|
34712
34713
|
if (tokenIssuer) {
|
|
34713
34714
|
authorizerOptions.tokenIssuer = tokenIssuer;
|
|
@@ -34775,6 +34776,11 @@ function normalizeConfig$c(config) {
|
|
|
34775
34776
|
: typeof source.reverse_auth_ttl_sec === 'number'
|
|
34776
34777
|
? source.reverse_auth_ttl_sec
|
|
34777
34778
|
: DEFAULT_REVERSE_AUTH_TTL_SEC;
|
|
34779
|
+
const enforceTokenSubjectNodeIdentity = typeof source.enforceTokenSubjectNodeIdentity === 'boolean'
|
|
34780
|
+
? source.enforceTokenSubjectNodeIdentity
|
|
34781
|
+
: typeof source.enforce_token_subject_node_identity === 'boolean'
|
|
34782
|
+
? source.enforce_token_subject_node_identity
|
|
34783
|
+
: false;
|
|
34778
34784
|
const tokenVerifierConfigInput = source.tokenVerifierConfig ?? source.token_verifier_config ?? null;
|
|
34779
34785
|
const tokenVerifierConfig = normalizeTokenVerifierConfig({
|
|
34780
34786
|
config: tokenVerifierConfigInput,
|
|
@@ -34793,6 +34799,7 @@ function normalizeConfig$c(config) {
|
|
|
34793
34799
|
maxTtlSec,
|
|
34794
34800
|
tokenVerifierConfig,
|
|
34795
34801
|
reverseAuthTtlSec: reverseAuthCandidate,
|
|
34802
|
+
enforceTokenSubjectNodeIdentity,
|
|
34796
34803
|
...(audience ? { audience } : {}),
|
|
34797
34804
|
};
|
|
34798
34805
|
if (tokenIssuerConfig) {
|
|
@@ -39830,6 +39837,10 @@ function normalizeOptions$4(raw) {
|
|
|
39830
39837
|
: typeof snake.aud === 'string'
|
|
39831
39838
|
? snake.aud
|
|
39832
39839
|
: undefined);
|
|
39840
|
+
const enforceTokenSubjectNodeIdentity = camel.enforceTokenSubjectNodeIdentity ??
|
|
39841
|
+
(typeof snake.enforce_token_subject_node_identity === 'boolean'
|
|
39842
|
+
? snake.enforce_token_subject_node_identity
|
|
39843
|
+
: undefined);
|
|
39833
39844
|
return {
|
|
39834
39845
|
tokenVerifier,
|
|
39835
39846
|
tokenIssuer,
|
|
@@ -39839,6 +39850,7 @@ function normalizeOptions$4(raw) {
|
|
|
39839
39850
|
defaultTtlSec,
|
|
39840
39851
|
maxTtlSec,
|
|
39841
39852
|
reverseAuthTtlSec,
|
|
39853
|
+
enforceTokenSubjectNodeIdentity,
|
|
39842
39854
|
};
|
|
39843
39855
|
}
|
|
39844
39856
|
class OAuth2Authorizer {
|
|
@@ -39852,6 +39864,8 @@ class OAuth2Authorizer {
|
|
|
39852
39864
|
this.requireScope = options.requireScope ?? true;
|
|
39853
39865
|
this.reverseAuthTtlSec =
|
|
39854
39866
|
options.reverseAuthTtlSec ?? DEFAULT_REVERSE_AUTH_TTL_SEC;
|
|
39867
|
+
this.enforceTokenSubjectNodeIdentity =
|
|
39868
|
+
options.enforceTokenSubjectNodeIdentity ?? false;
|
|
39855
39869
|
}
|
|
39856
39870
|
get tokenVerifier() {
|
|
39857
39871
|
return this.tokenVerifierImpl;
|
|
@@ -39981,6 +39995,13 @@ class OAuth2Authorizer {
|
|
|
39981
39995
|
});
|
|
39982
39996
|
return undefined;
|
|
39983
39997
|
}
|
|
39998
|
+
// Enforce token subject node identity if enabled
|
|
39999
|
+
if (this.enforceTokenSubjectNodeIdentity) {
|
|
40000
|
+
const validationResult = await this.validateTokenSubjectNodeIdentity(frame.systemId, claims);
|
|
40001
|
+
if (!validationResult) {
|
|
40002
|
+
return undefined;
|
|
40003
|
+
}
|
|
40004
|
+
}
|
|
39984
40005
|
claims.instance_id = claims.instance_id ?? frame.instanceId;
|
|
39985
40006
|
claims.assigned_path = claims.assigned_path ?? frame.assignedPath;
|
|
39986
40007
|
claims.accepted_capabilities =
|
|
@@ -40058,6 +40079,33 @@ class OAuth2Authorizer {
|
|
|
40058
40079
|
}
|
|
40059
40080
|
return false;
|
|
40060
40081
|
}
|
|
40082
|
+
async validateTokenSubjectNodeIdentity(systemId, claims) {
|
|
40083
|
+
const sub = claims.sub;
|
|
40084
|
+
if (typeof sub !== 'string' || sub.trim().length === 0) {
|
|
40085
|
+
logger$3.warning('oauth2_attach_missing_subject_claim', {
|
|
40086
|
+
system_id: systemId,
|
|
40087
|
+
});
|
|
40088
|
+
return false;
|
|
40089
|
+
}
|
|
40090
|
+
const expectedPrefix = await generateIdAsync({
|
|
40091
|
+
mode: 'fingerprint',
|
|
40092
|
+
material: sub,
|
|
40093
|
+
length: 8,
|
|
40094
|
+
});
|
|
40095
|
+
if (!systemId.startsWith(`${expectedPrefix}-`)) {
|
|
40096
|
+
logger$3.warning('oauth2_attach_node_identity_mismatch', {
|
|
40097
|
+
system_id: systemId,
|
|
40098
|
+
expected_prefix: expectedPrefix,
|
|
40099
|
+
subject: sub,
|
|
40100
|
+
});
|
|
40101
|
+
return false;
|
|
40102
|
+
}
|
|
40103
|
+
logger$3.debug('oauth2_attach_node_identity_verified', {
|
|
40104
|
+
system_id: systemId,
|
|
40105
|
+
expected_prefix: expectedPrefix,
|
|
40106
|
+
});
|
|
40107
|
+
return true;
|
|
40108
|
+
}
|
|
40061
40109
|
}
|
|
40062
40110
|
|
|
40063
40111
|
var oauth2Authorizer = /*#__PURE__*/Object.freeze({
|
|
@@ -86,6 +86,7 @@ class OAuth2AuthorizerFactory extends authorizer_factory_js_1.AuthorizerFactory
|
|
|
86
86
|
defaultTtlSec: normalized.defaultTtlSec,
|
|
87
87
|
maxTtlSec: normalized.maxTtlSec,
|
|
88
88
|
reverseAuthTtlSec: normalized.reverseAuthTtlSec,
|
|
89
|
+
enforceTokenSubjectNodeIdentity: normalized.enforceTokenSubjectNodeIdentity,
|
|
89
90
|
};
|
|
90
91
|
if (tokenIssuer) {
|
|
91
92
|
authorizerOptions.tokenIssuer = tokenIssuer;
|
|
@@ -154,6 +155,11 @@ function normalizeConfig(config) {
|
|
|
154
155
|
: typeof source.reverse_auth_ttl_sec === 'number'
|
|
155
156
|
? source.reverse_auth_ttl_sec
|
|
156
157
|
: ttl_constants_js_1.DEFAULT_REVERSE_AUTH_TTL_SEC;
|
|
158
|
+
const enforceTokenSubjectNodeIdentity = typeof source.enforceTokenSubjectNodeIdentity === 'boolean'
|
|
159
|
+
? source.enforceTokenSubjectNodeIdentity
|
|
160
|
+
: typeof source.enforce_token_subject_node_identity === 'boolean'
|
|
161
|
+
? source.enforce_token_subject_node_identity
|
|
162
|
+
: false;
|
|
157
163
|
const tokenVerifierConfigInput = source.tokenVerifierConfig ?? source.token_verifier_config ?? null;
|
|
158
164
|
const tokenVerifierConfig = normalizeTokenVerifierConfig({
|
|
159
165
|
config: tokenVerifierConfigInput,
|
|
@@ -172,6 +178,7 @@ function normalizeConfig(config) {
|
|
|
172
178
|
maxTtlSec,
|
|
173
179
|
tokenVerifierConfig,
|
|
174
180
|
reverseAuthTtlSec: reverseAuthCandidate,
|
|
181
|
+
enforceTokenSubjectNodeIdentity,
|
|
175
182
|
...(audience ? { audience } : {}),
|
|
176
183
|
};
|
|
177
184
|
if (tokenIssuerConfig) {
|
|
@@ -37,6 +37,10 @@ function normalizeOptions(raw) {
|
|
|
37
37
|
: typeof snake.aud === 'string'
|
|
38
38
|
? snake.aud
|
|
39
39
|
: undefined);
|
|
40
|
+
const enforceTokenSubjectNodeIdentity = camel.enforceTokenSubjectNodeIdentity ??
|
|
41
|
+
(typeof snake.enforce_token_subject_node_identity === 'boolean'
|
|
42
|
+
? snake.enforce_token_subject_node_identity
|
|
43
|
+
: undefined);
|
|
40
44
|
return {
|
|
41
45
|
tokenVerifier,
|
|
42
46
|
tokenIssuer,
|
|
@@ -46,6 +50,7 @@ function normalizeOptions(raw) {
|
|
|
46
50
|
defaultTtlSec,
|
|
47
51
|
maxTtlSec,
|
|
48
52
|
reverseAuthTtlSec,
|
|
53
|
+
enforceTokenSubjectNodeIdentity,
|
|
49
54
|
};
|
|
50
55
|
}
|
|
51
56
|
class OAuth2Authorizer {
|
|
@@ -59,6 +64,8 @@ class OAuth2Authorizer {
|
|
|
59
64
|
this.requireScope = options.requireScope ?? true;
|
|
60
65
|
this.reverseAuthTtlSec =
|
|
61
66
|
options.reverseAuthTtlSec ?? ttl_constants_js_1.DEFAULT_REVERSE_AUTH_TTL_SEC;
|
|
67
|
+
this.enforceTokenSubjectNodeIdentity =
|
|
68
|
+
options.enforceTokenSubjectNodeIdentity ?? false;
|
|
62
69
|
}
|
|
63
70
|
get tokenVerifier() {
|
|
64
71
|
return this.tokenVerifierImpl;
|
|
@@ -188,6 +195,13 @@ class OAuth2Authorizer {
|
|
|
188
195
|
});
|
|
189
196
|
return undefined;
|
|
190
197
|
}
|
|
198
|
+
// Enforce token subject node identity if enabled
|
|
199
|
+
if (this.enforceTokenSubjectNodeIdentity) {
|
|
200
|
+
const validationResult = await this.validateTokenSubjectNodeIdentity(frame.systemId, claims);
|
|
201
|
+
if (!validationResult) {
|
|
202
|
+
return undefined;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
191
205
|
claims.instance_id = claims.instance_id ?? frame.instanceId;
|
|
192
206
|
claims.assigned_path = claims.assigned_path ?? frame.assignedPath;
|
|
193
207
|
claims.accepted_capabilities =
|
|
@@ -265,5 +279,32 @@ class OAuth2Authorizer {
|
|
|
265
279
|
}
|
|
266
280
|
return false;
|
|
267
281
|
}
|
|
282
|
+
async validateTokenSubjectNodeIdentity(systemId, claims) {
|
|
283
|
+
const sub = claims.sub;
|
|
284
|
+
if (typeof sub !== 'string' || sub.trim().length === 0) {
|
|
285
|
+
logger.warning('oauth2_attach_missing_subject_claim', {
|
|
286
|
+
system_id: systemId,
|
|
287
|
+
});
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
const expectedPrefix = await (0, core_1.generateIdAsync)({
|
|
291
|
+
mode: 'fingerprint',
|
|
292
|
+
material: sub,
|
|
293
|
+
length: 8,
|
|
294
|
+
});
|
|
295
|
+
if (!systemId.startsWith(`${expectedPrefix}-`)) {
|
|
296
|
+
logger.warning('oauth2_attach_node_identity_mismatch', {
|
|
297
|
+
system_id: systemId,
|
|
298
|
+
expected_prefix: expectedPrefix,
|
|
299
|
+
subject: sub,
|
|
300
|
+
});
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
logger.debug('oauth2_attach_node_identity_verified', {
|
|
304
|
+
system_id: systemId,
|
|
305
|
+
expected_prefix: expectedPrefix,
|
|
306
|
+
});
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
268
309
|
}
|
|
269
310
|
exports.OAuth2Authorizer = OAuth2Authorizer;
|
package/dist/cjs/version.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// This file is auto-generated during build - do not edit manually
|
|
3
|
-
// Generated from package.json version: 0.3.
|
|
3
|
+
// Generated from package.json version: 0.3.17
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.VERSION = void 0;
|
|
6
6
|
/**
|
|
7
7
|
* The package version, injected at build time.
|
|
8
8
|
* @internal
|
|
9
9
|
*/
|
|
10
|
-
exports.VERSION = '0.3.
|
|
10
|
+
exports.VERSION = '0.3.17';
|
|
@@ -50,6 +50,7 @@ export class OAuth2AuthorizerFactory extends AuthorizerFactory {
|
|
|
50
50
|
defaultTtlSec: normalized.defaultTtlSec,
|
|
51
51
|
maxTtlSec: normalized.maxTtlSec,
|
|
52
52
|
reverseAuthTtlSec: normalized.reverseAuthTtlSec,
|
|
53
|
+
enforceTokenSubjectNodeIdentity: normalized.enforceTokenSubjectNodeIdentity,
|
|
53
54
|
};
|
|
54
55
|
if (tokenIssuer) {
|
|
55
56
|
authorizerOptions.tokenIssuer = tokenIssuer;
|
|
@@ -117,6 +118,11 @@ function normalizeConfig(config) {
|
|
|
117
118
|
: typeof source.reverse_auth_ttl_sec === 'number'
|
|
118
119
|
? source.reverse_auth_ttl_sec
|
|
119
120
|
: DEFAULT_REVERSE_AUTH_TTL_SEC;
|
|
121
|
+
const enforceTokenSubjectNodeIdentity = typeof source.enforceTokenSubjectNodeIdentity === 'boolean'
|
|
122
|
+
? source.enforceTokenSubjectNodeIdentity
|
|
123
|
+
: typeof source.enforce_token_subject_node_identity === 'boolean'
|
|
124
|
+
? source.enforce_token_subject_node_identity
|
|
125
|
+
: false;
|
|
120
126
|
const tokenVerifierConfigInput = source.tokenVerifierConfig ?? source.token_verifier_config ?? null;
|
|
121
127
|
const tokenVerifierConfig = normalizeTokenVerifierConfig({
|
|
122
128
|
config: tokenVerifierConfigInput,
|
|
@@ -135,6 +141,7 @@ function normalizeConfig(config) {
|
|
|
135
141
|
maxTtlSec,
|
|
136
142
|
tokenVerifierConfig,
|
|
137
143
|
reverseAuthTtlSec: reverseAuthCandidate,
|
|
144
|
+
enforceTokenSubjectNodeIdentity,
|
|
138
145
|
...(audience ? { audience } : {}),
|
|
139
146
|
};
|
|
140
147
|
if (tokenIssuerConfig) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createAuthorizationContext } from '@naylence/core';
|
|
1
|
+
import { createAuthorizationContext, generateIdAsync } from '@naylence/core';
|
|
2
2
|
import { DEFAULT_REVERSE_AUTH_TTL_SEC } from '../../constants/ttl-constants.js';
|
|
3
3
|
import { getLogger } from '../../util/logging.js';
|
|
4
4
|
const logger = getLogger('naylence.fame.security.auth.oauth2_authorizer');
|
|
@@ -34,6 +34,10 @@ function normalizeOptions(raw) {
|
|
|
34
34
|
: typeof snake.aud === 'string'
|
|
35
35
|
? snake.aud
|
|
36
36
|
: undefined);
|
|
37
|
+
const enforceTokenSubjectNodeIdentity = camel.enforceTokenSubjectNodeIdentity ??
|
|
38
|
+
(typeof snake.enforce_token_subject_node_identity === 'boolean'
|
|
39
|
+
? snake.enforce_token_subject_node_identity
|
|
40
|
+
: undefined);
|
|
37
41
|
return {
|
|
38
42
|
tokenVerifier,
|
|
39
43
|
tokenIssuer,
|
|
@@ -43,6 +47,7 @@ function normalizeOptions(raw) {
|
|
|
43
47
|
defaultTtlSec,
|
|
44
48
|
maxTtlSec,
|
|
45
49
|
reverseAuthTtlSec,
|
|
50
|
+
enforceTokenSubjectNodeIdentity,
|
|
46
51
|
};
|
|
47
52
|
}
|
|
48
53
|
export class OAuth2Authorizer {
|
|
@@ -56,6 +61,8 @@ export class OAuth2Authorizer {
|
|
|
56
61
|
this.requireScope = options.requireScope ?? true;
|
|
57
62
|
this.reverseAuthTtlSec =
|
|
58
63
|
options.reverseAuthTtlSec ?? DEFAULT_REVERSE_AUTH_TTL_SEC;
|
|
64
|
+
this.enforceTokenSubjectNodeIdentity =
|
|
65
|
+
options.enforceTokenSubjectNodeIdentity ?? false;
|
|
59
66
|
}
|
|
60
67
|
get tokenVerifier() {
|
|
61
68
|
return this.tokenVerifierImpl;
|
|
@@ -185,6 +192,13 @@ export class OAuth2Authorizer {
|
|
|
185
192
|
});
|
|
186
193
|
return undefined;
|
|
187
194
|
}
|
|
195
|
+
// Enforce token subject node identity if enabled
|
|
196
|
+
if (this.enforceTokenSubjectNodeIdentity) {
|
|
197
|
+
const validationResult = await this.validateTokenSubjectNodeIdentity(frame.systemId, claims);
|
|
198
|
+
if (!validationResult) {
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
188
202
|
claims.instance_id = claims.instance_id ?? frame.instanceId;
|
|
189
203
|
claims.assigned_path = claims.assigned_path ?? frame.assignedPath;
|
|
190
204
|
claims.accepted_capabilities =
|
|
@@ -262,4 +276,31 @@ export class OAuth2Authorizer {
|
|
|
262
276
|
}
|
|
263
277
|
return false;
|
|
264
278
|
}
|
|
279
|
+
async validateTokenSubjectNodeIdentity(systemId, claims) {
|
|
280
|
+
const sub = claims.sub;
|
|
281
|
+
if (typeof sub !== 'string' || sub.trim().length === 0) {
|
|
282
|
+
logger.warning('oauth2_attach_missing_subject_claim', {
|
|
283
|
+
system_id: systemId,
|
|
284
|
+
});
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
const expectedPrefix = await generateIdAsync({
|
|
288
|
+
mode: 'fingerprint',
|
|
289
|
+
material: sub,
|
|
290
|
+
length: 8,
|
|
291
|
+
});
|
|
292
|
+
if (!systemId.startsWith(`${expectedPrefix}-`)) {
|
|
293
|
+
logger.warning('oauth2_attach_node_identity_mismatch', {
|
|
294
|
+
system_id: systemId,
|
|
295
|
+
expected_prefix: expectedPrefix,
|
|
296
|
+
subject: sub,
|
|
297
|
+
});
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
logger.debug('oauth2_attach_node_identity_verified', {
|
|
301
|
+
system_id: systemId,
|
|
302
|
+
expected_prefix: expectedPrefix,
|
|
303
|
+
});
|
|
304
|
+
return true;
|
|
305
|
+
}
|
|
265
306
|
}
|
package/dist/esm/version.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// This file is auto-generated during build - do not edit manually
|
|
2
|
-
// Generated from package.json version: 0.3.
|
|
2
|
+
// Generated from package.json version: 0.3.17
|
|
3
3
|
/**
|
|
4
4
|
* The package version, injected at build time.
|
|
5
5
|
* @internal
|
|
6
6
|
*/
|
|
7
|
-
export const VERSION = '0.3.
|
|
7
|
+
export const VERSION = '0.3.17';
|
package/dist/node/index.cjs
CHANGED
|
@@ -14,12 +14,12 @@ var fastify = require('fastify');
|
|
|
14
14
|
var websocketPlugin = require('@fastify/websocket');
|
|
15
15
|
|
|
16
16
|
// This file is auto-generated during build - do not edit manually
|
|
17
|
-
// Generated from package.json version: 0.3.
|
|
17
|
+
// Generated from package.json version: 0.3.17
|
|
18
18
|
/**
|
|
19
19
|
* The package version, injected at build time.
|
|
20
20
|
* @internal
|
|
21
21
|
*/
|
|
22
|
-
const VERSION = '0.3.
|
|
22
|
+
const VERSION = '0.3.17';
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Fame protocol specific error classes with WebSocket close codes and proper inheritance.
|
|
@@ -33260,6 +33260,7 @@ class OAuth2AuthorizerFactory extends AuthorizerFactory {
|
|
|
33260
33260
|
defaultTtlSec: normalized.defaultTtlSec,
|
|
33261
33261
|
maxTtlSec: normalized.maxTtlSec,
|
|
33262
33262
|
reverseAuthTtlSec: normalized.reverseAuthTtlSec,
|
|
33263
|
+
enforceTokenSubjectNodeIdentity: normalized.enforceTokenSubjectNodeIdentity,
|
|
33263
33264
|
};
|
|
33264
33265
|
if (tokenIssuer) {
|
|
33265
33266
|
authorizerOptions.tokenIssuer = tokenIssuer;
|
|
@@ -33327,6 +33328,11 @@ function normalizeConfig$c(config) {
|
|
|
33327
33328
|
: typeof source.reverse_auth_ttl_sec === 'number'
|
|
33328
33329
|
? source.reverse_auth_ttl_sec
|
|
33329
33330
|
: DEFAULT_REVERSE_AUTH_TTL_SEC;
|
|
33331
|
+
const enforceTokenSubjectNodeIdentity = typeof source.enforceTokenSubjectNodeIdentity === 'boolean'
|
|
33332
|
+
? source.enforceTokenSubjectNodeIdentity
|
|
33333
|
+
: typeof source.enforce_token_subject_node_identity === 'boolean'
|
|
33334
|
+
? source.enforce_token_subject_node_identity
|
|
33335
|
+
: false;
|
|
33330
33336
|
const tokenVerifierConfigInput = source.tokenVerifierConfig ?? source.token_verifier_config ?? null;
|
|
33331
33337
|
const tokenVerifierConfig = normalizeTokenVerifierConfig({
|
|
33332
33338
|
config: tokenVerifierConfigInput,
|
|
@@ -33345,6 +33351,7 @@ function normalizeConfig$c(config) {
|
|
|
33345
33351
|
maxTtlSec,
|
|
33346
33352
|
tokenVerifierConfig,
|
|
33347
33353
|
reverseAuthTtlSec: reverseAuthCandidate,
|
|
33354
|
+
enforceTokenSubjectNodeIdentity,
|
|
33348
33355
|
...(audience ? { audience } : {}),
|
|
33349
33356
|
};
|
|
33350
33357
|
if (tokenIssuerConfig) {
|
|
@@ -39634,6 +39641,10 @@ function normalizeOptions$4(raw) {
|
|
|
39634
39641
|
: typeof snake.aud === 'string'
|
|
39635
39642
|
? snake.aud
|
|
39636
39643
|
: undefined);
|
|
39644
|
+
const enforceTokenSubjectNodeIdentity = camel.enforceTokenSubjectNodeIdentity ??
|
|
39645
|
+
(typeof snake.enforce_token_subject_node_identity === 'boolean'
|
|
39646
|
+
? snake.enforce_token_subject_node_identity
|
|
39647
|
+
: undefined);
|
|
39637
39648
|
return {
|
|
39638
39649
|
tokenVerifier,
|
|
39639
39650
|
tokenIssuer,
|
|
@@ -39643,6 +39654,7 @@ function normalizeOptions$4(raw) {
|
|
|
39643
39654
|
defaultTtlSec,
|
|
39644
39655
|
maxTtlSec,
|
|
39645
39656
|
reverseAuthTtlSec,
|
|
39657
|
+
enforceTokenSubjectNodeIdentity,
|
|
39646
39658
|
};
|
|
39647
39659
|
}
|
|
39648
39660
|
class OAuth2Authorizer {
|
|
@@ -39656,6 +39668,8 @@ class OAuth2Authorizer {
|
|
|
39656
39668
|
this.requireScope = options.requireScope ?? true;
|
|
39657
39669
|
this.reverseAuthTtlSec =
|
|
39658
39670
|
options.reverseAuthTtlSec ?? DEFAULT_REVERSE_AUTH_TTL_SEC;
|
|
39671
|
+
this.enforceTokenSubjectNodeIdentity =
|
|
39672
|
+
options.enforceTokenSubjectNodeIdentity ?? false;
|
|
39659
39673
|
}
|
|
39660
39674
|
get tokenVerifier() {
|
|
39661
39675
|
return this.tokenVerifierImpl;
|
|
@@ -39785,6 +39799,13 @@ class OAuth2Authorizer {
|
|
|
39785
39799
|
});
|
|
39786
39800
|
return undefined;
|
|
39787
39801
|
}
|
|
39802
|
+
// Enforce token subject node identity if enabled
|
|
39803
|
+
if (this.enforceTokenSubjectNodeIdentity) {
|
|
39804
|
+
const validationResult = await this.validateTokenSubjectNodeIdentity(frame.systemId, claims);
|
|
39805
|
+
if (!validationResult) {
|
|
39806
|
+
return undefined;
|
|
39807
|
+
}
|
|
39808
|
+
}
|
|
39788
39809
|
claims.instance_id = claims.instance_id ?? frame.instanceId;
|
|
39789
39810
|
claims.assigned_path = claims.assigned_path ?? frame.assignedPath;
|
|
39790
39811
|
claims.accepted_capabilities =
|
|
@@ -39862,6 +39883,33 @@ class OAuth2Authorizer {
|
|
|
39862
39883
|
}
|
|
39863
39884
|
return false;
|
|
39864
39885
|
}
|
|
39886
|
+
async validateTokenSubjectNodeIdentity(systemId, claims) {
|
|
39887
|
+
const sub = claims.sub;
|
|
39888
|
+
if (typeof sub !== 'string' || sub.trim().length === 0) {
|
|
39889
|
+
logger$3.warning('oauth2_attach_missing_subject_claim', {
|
|
39890
|
+
system_id: systemId,
|
|
39891
|
+
});
|
|
39892
|
+
return false;
|
|
39893
|
+
}
|
|
39894
|
+
const expectedPrefix = await core.generateIdAsync({
|
|
39895
|
+
mode: 'fingerprint',
|
|
39896
|
+
material: sub,
|
|
39897
|
+
length: 8,
|
|
39898
|
+
});
|
|
39899
|
+
if (!systemId.startsWith(`${expectedPrefix}-`)) {
|
|
39900
|
+
logger$3.warning('oauth2_attach_node_identity_mismatch', {
|
|
39901
|
+
system_id: systemId,
|
|
39902
|
+
expected_prefix: expectedPrefix,
|
|
39903
|
+
subject: sub,
|
|
39904
|
+
});
|
|
39905
|
+
return false;
|
|
39906
|
+
}
|
|
39907
|
+
logger$3.debug('oauth2_attach_node_identity_verified', {
|
|
39908
|
+
system_id: systemId,
|
|
39909
|
+
expected_prefix: expectedPrefix,
|
|
39910
|
+
});
|
|
39911
|
+
return true;
|
|
39912
|
+
}
|
|
39865
39913
|
}
|
|
39866
39914
|
|
|
39867
39915
|
var oauth2Authorizer = /*#__PURE__*/Object.freeze({
|
package/dist/node/index.mjs
CHANGED
|
@@ -13,12 +13,12 @@ import fastify from 'fastify';
|
|
|
13
13
|
import websocketPlugin from '@fastify/websocket';
|
|
14
14
|
|
|
15
15
|
// This file is auto-generated during build - do not edit manually
|
|
16
|
-
// Generated from package.json version: 0.3.
|
|
16
|
+
// Generated from package.json version: 0.3.17
|
|
17
17
|
/**
|
|
18
18
|
* The package version, injected at build time.
|
|
19
19
|
* @internal
|
|
20
20
|
*/
|
|
21
|
-
const VERSION = '0.3.
|
|
21
|
+
const VERSION = '0.3.17';
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Fame protocol specific error classes with WebSocket close codes and proper inheritance.
|
|
@@ -33259,6 +33259,7 @@ class OAuth2AuthorizerFactory extends AuthorizerFactory {
|
|
|
33259
33259
|
defaultTtlSec: normalized.defaultTtlSec,
|
|
33260
33260
|
maxTtlSec: normalized.maxTtlSec,
|
|
33261
33261
|
reverseAuthTtlSec: normalized.reverseAuthTtlSec,
|
|
33262
|
+
enforceTokenSubjectNodeIdentity: normalized.enforceTokenSubjectNodeIdentity,
|
|
33262
33263
|
};
|
|
33263
33264
|
if (tokenIssuer) {
|
|
33264
33265
|
authorizerOptions.tokenIssuer = tokenIssuer;
|
|
@@ -33326,6 +33327,11 @@ function normalizeConfig$c(config) {
|
|
|
33326
33327
|
: typeof source.reverse_auth_ttl_sec === 'number'
|
|
33327
33328
|
? source.reverse_auth_ttl_sec
|
|
33328
33329
|
: DEFAULT_REVERSE_AUTH_TTL_SEC;
|
|
33330
|
+
const enforceTokenSubjectNodeIdentity = typeof source.enforceTokenSubjectNodeIdentity === 'boolean'
|
|
33331
|
+
? source.enforceTokenSubjectNodeIdentity
|
|
33332
|
+
: typeof source.enforce_token_subject_node_identity === 'boolean'
|
|
33333
|
+
? source.enforce_token_subject_node_identity
|
|
33334
|
+
: false;
|
|
33329
33335
|
const tokenVerifierConfigInput = source.tokenVerifierConfig ?? source.token_verifier_config ?? null;
|
|
33330
33336
|
const tokenVerifierConfig = normalizeTokenVerifierConfig({
|
|
33331
33337
|
config: tokenVerifierConfigInput,
|
|
@@ -33344,6 +33350,7 @@ function normalizeConfig$c(config) {
|
|
|
33344
33350
|
maxTtlSec,
|
|
33345
33351
|
tokenVerifierConfig,
|
|
33346
33352
|
reverseAuthTtlSec: reverseAuthCandidate,
|
|
33353
|
+
enforceTokenSubjectNodeIdentity,
|
|
33347
33354
|
...(audience ? { audience } : {}),
|
|
33348
33355
|
};
|
|
33349
33356
|
if (tokenIssuerConfig) {
|
|
@@ -39633,6 +39640,10 @@ function normalizeOptions$4(raw) {
|
|
|
39633
39640
|
: typeof snake.aud === 'string'
|
|
39634
39641
|
? snake.aud
|
|
39635
39642
|
: undefined);
|
|
39643
|
+
const enforceTokenSubjectNodeIdentity = camel.enforceTokenSubjectNodeIdentity ??
|
|
39644
|
+
(typeof snake.enforce_token_subject_node_identity === 'boolean'
|
|
39645
|
+
? snake.enforce_token_subject_node_identity
|
|
39646
|
+
: undefined);
|
|
39636
39647
|
return {
|
|
39637
39648
|
tokenVerifier,
|
|
39638
39649
|
tokenIssuer,
|
|
@@ -39642,6 +39653,7 @@ function normalizeOptions$4(raw) {
|
|
|
39642
39653
|
defaultTtlSec,
|
|
39643
39654
|
maxTtlSec,
|
|
39644
39655
|
reverseAuthTtlSec,
|
|
39656
|
+
enforceTokenSubjectNodeIdentity,
|
|
39645
39657
|
};
|
|
39646
39658
|
}
|
|
39647
39659
|
class OAuth2Authorizer {
|
|
@@ -39655,6 +39667,8 @@ class OAuth2Authorizer {
|
|
|
39655
39667
|
this.requireScope = options.requireScope ?? true;
|
|
39656
39668
|
this.reverseAuthTtlSec =
|
|
39657
39669
|
options.reverseAuthTtlSec ?? DEFAULT_REVERSE_AUTH_TTL_SEC;
|
|
39670
|
+
this.enforceTokenSubjectNodeIdentity =
|
|
39671
|
+
options.enforceTokenSubjectNodeIdentity ?? false;
|
|
39658
39672
|
}
|
|
39659
39673
|
get tokenVerifier() {
|
|
39660
39674
|
return this.tokenVerifierImpl;
|
|
@@ -39784,6 +39798,13 @@ class OAuth2Authorizer {
|
|
|
39784
39798
|
});
|
|
39785
39799
|
return undefined;
|
|
39786
39800
|
}
|
|
39801
|
+
// Enforce token subject node identity if enabled
|
|
39802
|
+
if (this.enforceTokenSubjectNodeIdentity) {
|
|
39803
|
+
const validationResult = await this.validateTokenSubjectNodeIdentity(frame.systemId, claims);
|
|
39804
|
+
if (!validationResult) {
|
|
39805
|
+
return undefined;
|
|
39806
|
+
}
|
|
39807
|
+
}
|
|
39787
39808
|
claims.instance_id = claims.instance_id ?? frame.instanceId;
|
|
39788
39809
|
claims.assigned_path = claims.assigned_path ?? frame.assignedPath;
|
|
39789
39810
|
claims.accepted_capabilities =
|
|
@@ -39861,6 +39882,33 @@ class OAuth2Authorizer {
|
|
|
39861
39882
|
}
|
|
39862
39883
|
return false;
|
|
39863
39884
|
}
|
|
39885
|
+
async validateTokenSubjectNodeIdentity(systemId, claims) {
|
|
39886
|
+
const sub = claims.sub;
|
|
39887
|
+
if (typeof sub !== 'string' || sub.trim().length === 0) {
|
|
39888
|
+
logger$3.warning('oauth2_attach_missing_subject_claim', {
|
|
39889
|
+
system_id: systemId,
|
|
39890
|
+
});
|
|
39891
|
+
return false;
|
|
39892
|
+
}
|
|
39893
|
+
const expectedPrefix = await generateIdAsync({
|
|
39894
|
+
mode: 'fingerprint',
|
|
39895
|
+
material: sub,
|
|
39896
|
+
length: 8,
|
|
39897
|
+
});
|
|
39898
|
+
if (!systemId.startsWith(`${expectedPrefix}-`)) {
|
|
39899
|
+
logger$3.warning('oauth2_attach_node_identity_mismatch', {
|
|
39900
|
+
system_id: systemId,
|
|
39901
|
+
expected_prefix: expectedPrefix,
|
|
39902
|
+
subject: sub,
|
|
39903
|
+
});
|
|
39904
|
+
return false;
|
|
39905
|
+
}
|
|
39906
|
+
logger$3.debug('oauth2_attach_node_identity_verified', {
|
|
39907
|
+
system_id: systemId,
|
|
39908
|
+
expected_prefix: expectedPrefix,
|
|
39909
|
+
});
|
|
39910
|
+
return true;
|
|
39911
|
+
}
|
|
39864
39912
|
}
|
|
39865
39913
|
|
|
39866
39914
|
var oauth2Authorizer = /*#__PURE__*/Object.freeze({
|
package/dist/node/node.cjs
CHANGED
|
@@ -4426,12 +4426,12 @@ async function ensureRuntimeFactoriesRegistered(registry = factory.Registry) {
|
|
|
4426
4426
|
}
|
|
4427
4427
|
|
|
4428
4428
|
// This file is auto-generated during build - do not edit manually
|
|
4429
|
-
// Generated from package.json version: 0.3.
|
|
4429
|
+
// Generated from package.json version: 0.3.17
|
|
4430
4430
|
/**
|
|
4431
4431
|
* The package version, injected at build time.
|
|
4432
4432
|
* @internal
|
|
4433
4433
|
*/
|
|
4434
|
-
const VERSION = '0.3.
|
|
4434
|
+
const VERSION = '0.3.17';
|
|
4435
4435
|
|
|
4436
4436
|
let initialized = false;
|
|
4437
4437
|
const runtimePlugin = {
|
|
@@ -38001,6 +38001,7 @@ class OAuth2AuthorizerFactory extends AuthorizerFactory {
|
|
|
38001
38001
|
defaultTtlSec: normalized.defaultTtlSec,
|
|
38002
38002
|
maxTtlSec: normalized.maxTtlSec,
|
|
38003
38003
|
reverseAuthTtlSec: normalized.reverseAuthTtlSec,
|
|
38004
|
+
enforceTokenSubjectNodeIdentity: normalized.enforceTokenSubjectNodeIdentity,
|
|
38004
38005
|
};
|
|
38005
38006
|
if (tokenIssuer) {
|
|
38006
38007
|
authorizerOptions.tokenIssuer = tokenIssuer;
|
|
@@ -38068,6 +38069,11 @@ function normalizeConfig$c(config) {
|
|
|
38068
38069
|
: typeof source.reverse_auth_ttl_sec === 'number'
|
|
38069
38070
|
? source.reverse_auth_ttl_sec
|
|
38070
38071
|
: DEFAULT_REVERSE_AUTH_TTL_SEC;
|
|
38072
|
+
const enforceTokenSubjectNodeIdentity = typeof source.enforceTokenSubjectNodeIdentity === 'boolean'
|
|
38073
|
+
? source.enforceTokenSubjectNodeIdentity
|
|
38074
|
+
: typeof source.enforce_token_subject_node_identity === 'boolean'
|
|
38075
|
+
? source.enforce_token_subject_node_identity
|
|
38076
|
+
: false;
|
|
38071
38077
|
const tokenVerifierConfigInput = source.tokenVerifierConfig ?? source.token_verifier_config ?? null;
|
|
38072
38078
|
const tokenVerifierConfig = normalizeTokenVerifierConfig({
|
|
38073
38079
|
config: tokenVerifierConfigInput,
|
|
@@ -38086,6 +38092,7 @@ function normalizeConfig$c(config) {
|
|
|
38086
38092
|
maxTtlSec,
|
|
38087
38093
|
tokenVerifierConfig,
|
|
38088
38094
|
reverseAuthTtlSec: reverseAuthCandidate,
|
|
38095
|
+
enforceTokenSubjectNodeIdentity,
|
|
38089
38096
|
...(audience ? { audience } : {}),
|
|
38090
38097
|
};
|
|
38091
38098
|
if (tokenIssuerConfig) {
|
|
@@ -41968,6 +41975,10 @@ function normalizeOptions$4(raw) {
|
|
|
41968
41975
|
: typeof snake.aud === 'string'
|
|
41969
41976
|
? snake.aud
|
|
41970
41977
|
: undefined);
|
|
41978
|
+
const enforceTokenSubjectNodeIdentity = camel.enforceTokenSubjectNodeIdentity ??
|
|
41979
|
+
(typeof snake.enforce_token_subject_node_identity === 'boolean'
|
|
41980
|
+
? snake.enforce_token_subject_node_identity
|
|
41981
|
+
: undefined);
|
|
41971
41982
|
return {
|
|
41972
41983
|
tokenVerifier,
|
|
41973
41984
|
tokenIssuer,
|
|
@@ -41977,6 +41988,7 @@ function normalizeOptions$4(raw) {
|
|
|
41977
41988
|
defaultTtlSec,
|
|
41978
41989
|
maxTtlSec,
|
|
41979
41990
|
reverseAuthTtlSec,
|
|
41991
|
+
enforceTokenSubjectNodeIdentity,
|
|
41980
41992
|
};
|
|
41981
41993
|
}
|
|
41982
41994
|
class OAuth2Authorizer {
|
|
@@ -41990,6 +42002,8 @@ class OAuth2Authorizer {
|
|
|
41990
42002
|
this.requireScope = options.requireScope ?? true;
|
|
41991
42003
|
this.reverseAuthTtlSec =
|
|
41992
42004
|
options.reverseAuthTtlSec ?? DEFAULT_REVERSE_AUTH_TTL_SEC;
|
|
42005
|
+
this.enforceTokenSubjectNodeIdentity =
|
|
42006
|
+
options.enforceTokenSubjectNodeIdentity ?? false;
|
|
41993
42007
|
}
|
|
41994
42008
|
get tokenVerifier() {
|
|
41995
42009
|
return this.tokenVerifierImpl;
|
|
@@ -42119,6 +42133,13 @@ class OAuth2Authorizer {
|
|
|
42119
42133
|
});
|
|
42120
42134
|
return undefined;
|
|
42121
42135
|
}
|
|
42136
|
+
// Enforce token subject node identity if enabled
|
|
42137
|
+
if (this.enforceTokenSubjectNodeIdentity) {
|
|
42138
|
+
const validationResult = await this.validateTokenSubjectNodeIdentity(frame.systemId, claims);
|
|
42139
|
+
if (!validationResult) {
|
|
42140
|
+
return undefined;
|
|
42141
|
+
}
|
|
42142
|
+
}
|
|
42122
42143
|
claims.instance_id = claims.instance_id ?? frame.instanceId;
|
|
42123
42144
|
claims.assigned_path = claims.assigned_path ?? frame.assignedPath;
|
|
42124
42145
|
claims.accepted_capabilities =
|
|
@@ -42196,6 +42217,33 @@ class OAuth2Authorizer {
|
|
|
42196
42217
|
}
|
|
42197
42218
|
return false;
|
|
42198
42219
|
}
|
|
42220
|
+
async validateTokenSubjectNodeIdentity(systemId, claims) {
|
|
42221
|
+
const sub = claims.sub;
|
|
42222
|
+
if (typeof sub !== 'string' || sub.trim().length === 0) {
|
|
42223
|
+
logger$3.warning('oauth2_attach_missing_subject_claim', {
|
|
42224
|
+
system_id: systemId,
|
|
42225
|
+
});
|
|
42226
|
+
return false;
|
|
42227
|
+
}
|
|
42228
|
+
const expectedPrefix = await core.generateIdAsync({
|
|
42229
|
+
mode: 'fingerprint',
|
|
42230
|
+
material: sub,
|
|
42231
|
+
length: 8,
|
|
42232
|
+
});
|
|
42233
|
+
if (!systemId.startsWith(`${expectedPrefix}-`)) {
|
|
42234
|
+
logger$3.warning('oauth2_attach_node_identity_mismatch', {
|
|
42235
|
+
system_id: systemId,
|
|
42236
|
+
expected_prefix: expectedPrefix,
|
|
42237
|
+
subject: sub,
|
|
42238
|
+
});
|
|
42239
|
+
return false;
|
|
42240
|
+
}
|
|
42241
|
+
logger$3.debug('oauth2_attach_node_identity_verified', {
|
|
42242
|
+
system_id: systemId,
|
|
42243
|
+
expected_prefix: expectedPrefix,
|
|
42244
|
+
});
|
|
42245
|
+
return true;
|
|
42246
|
+
}
|
|
42199
42247
|
}
|
|
42200
42248
|
|
|
42201
42249
|
var oauth2Authorizer = /*#__PURE__*/Object.freeze({
|
package/dist/node/node.mjs
CHANGED
|
@@ -4425,12 +4425,12 @@ async function ensureRuntimeFactoriesRegistered(registry = Registry) {
|
|
|
4425
4425
|
}
|
|
4426
4426
|
|
|
4427
4427
|
// This file is auto-generated during build - do not edit manually
|
|
4428
|
-
// Generated from package.json version: 0.3.
|
|
4428
|
+
// Generated from package.json version: 0.3.17
|
|
4429
4429
|
/**
|
|
4430
4430
|
* The package version, injected at build time.
|
|
4431
4431
|
* @internal
|
|
4432
4432
|
*/
|
|
4433
|
-
const VERSION = '0.3.
|
|
4433
|
+
const VERSION = '0.3.17';
|
|
4434
4434
|
|
|
4435
4435
|
let initialized = false;
|
|
4436
4436
|
const runtimePlugin = {
|
|
@@ -38000,6 +38000,7 @@ class OAuth2AuthorizerFactory extends AuthorizerFactory {
|
|
|
38000
38000
|
defaultTtlSec: normalized.defaultTtlSec,
|
|
38001
38001
|
maxTtlSec: normalized.maxTtlSec,
|
|
38002
38002
|
reverseAuthTtlSec: normalized.reverseAuthTtlSec,
|
|
38003
|
+
enforceTokenSubjectNodeIdentity: normalized.enforceTokenSubjectNodeIdentity,
|
|
38003
38004
|
};
|
|
38004
38005
|
if (tokenIssuer) {
|
|
38005
38006
|
authorizerOptions.tokenIssuer = tokenIssuer;
|
|
@@ -38067,6 +38068,11 @@ function normalizeConfig$c(config) {
|
|
|
38067
38068
|
: typeof source.reverse_auth_ttl_sec === 'number'
|
|
38068
38069
|
? source.reverse_auth_ttl_sec
|
|
38069
38070
|
: DEFAULT_REVERSE_AUTH_TTL_SEC;
|
|
38071
|
+
const enforceTokenSubjectNodeIdentity = typeof source.enforceTokenSubjectNodeIdentity === 'boolean'
|
|
38072
|
+
? source.enforceTokenSubjectNodeIdentity
|
|
38073
|
+
: typeof source.enforce_token_subject_node_identity === 'boolean'
|
|
38074
|
+
? source.enforce_token_subject_node_identity
|
|
38075
|
+
: false;
|
|
38070
38076
|
const tokenVerifierConfigInput = source.tokenVerifierConfig ?? source.token_verifier_config ?? null;
|
|
38071
38077
|
const tokenVerifierConfig = normalizeTokenVerifierConfig({
|
|
38072
38078
|
config: tokenVerifierConfigInput,
|
|
@@ -38085,6 +38091,7 @@ function normalizeConfig$c(config) {
|
|
|
38085
38091
|
maxTtlSec,
|
|
38086
38092
|
tokenVerifierConfig,
|
|
38087
38093
|
reverseAuthTtlSec: reverseAuthCandidate,
|
|
38094
|
+
enforceTokenSubjectNodeIdentity,
|
|
38088
38095
|
...(audience ? { audience } : {}),
|
|
38089
38096
|
};
|
|
38090
38097
|
if (tokenIssuerConfig) {
|
|
@@ -41967,6 +41974,10 @@ function normalizeOptions$4(raw) {
|
|
|
41967
41974
|
: typeof snake.aud === 'string'
|
|
41968
41975
|
? snake.aud
|
|
41969
41976
|
: undefined);
|
|
41977
|
+
const enforceTokenSubjectNodeIdentity = camel.enforceTokenSubjectNodeIdentity ??
|
|
41978
|
+
(typeof snake.enforce_token_subject_node_identity === 'boolean'
|
|
41979
|
+
? snake.enforce_token_subject_node_identity
|
|
41980
|
+
: undefined);
|
|
41970
41981
|
return {
|
|
41971
41982
|
tokenVerifier,
|
|
41972
41983
|
tokenIssuer,
|
|
@@ -41976,6 +41987,7 @@ function normalizeOptions$4(raw) {
|
|
|
41976
41987
|
defaultTtlSec,
|
|
41977
41988
|
maxTtlSec,
|
|
41978
41989
|
reverseAuthTtlSec,
|
|
41990
|
+
enforceTokenSubjectNodeIdentity,
|
|
41979
41991
|
};
|
|
41980
41992
|
}
|
|
41981
41993
|
class OAuth2Authorizer {
|
|
@@ -41989,6 +42001,8 @@ class OAuth2Authorizer {
|
|
|
41989
42001
|
this.requireScope = options.requireScope ?? true;
|
|
41990
42002
|
this.reverseAuthTtlSec =
|
|
41991
42003
|
options.reverseAuthTtlSec ?? DEFAULT_REVERSE_AUTH_TTL_SEC;
|
|
42004
|
+
this.enforceTokenSubjectNodeIdentity =
|
|
42005
|
+
options.enforceTokenSubjectNodeIdentity ?? false;
|
|
41992
42006
|
}
|
|
41993
42007
|
get tokenVerifier() {
|
|
41994
42008
|
return this.tokenVerifierImpl;
|
|
@@ -42118,6 +42132,13 @@ class OAuth2Authorizer {
|
|
|
42118
42132
|
});
|
|
42119
42133
|
return undefined;
|
|
42120
42134
|
}
|
|
42135
|
+
// Enforce token subject node identity if enabled
|
|
42136
|
+
if (this.enforceTokenSubjectNodeIdentity) {
|
|
42137
|
+
const validationResult = await this.validateTokenSubjectNodeIdentity(frame.systemId, claims);
|
|
42138
|
+
if (!validationResult) {
|
|
42139
|
+
return undefined;
|
|
42140
|
+
}
|
|
42141
|
+
}
|
|
42121
42142
|
claims.instance_id = claims.instance_id ?? frame.instanceId;
|
|
42122
42143
|
claims.assigned_path = claims.assigned_path ?? frame.assignedPath;
|
|
42123
42144
|
claims.accepted_capabilities =
|
|
@@ -42195,6 +42216,33 @@ class OAuth2Authorizer {
|
|
|
42195
42216
|
}
|
|
42196
42217
|
return false;
|
|
42197
42218
|
}
|
|
42219
|
+
async validateTokenSubjectNodeIdentity(systemId, claims) {
|
|
42220
|
+
const sub = claims.sub;
|
|
42221
|
+
if (typeof sub !== 'string' || sub.trim().length === 0) {
|
|
42222
|
+
logger$3.warning('oauth2_attach_missing_subject_claim', {
|
|
42223
|
+
system_id: systemId,
|
|
42224
|
+
});
|
|
42225
|
+
return false;
|
|
42226
|
+
}
|
|
42227
|
+
const expectedPrefix = await generateIdAsync({
|
|
42228
|
+
mode: 'fingerprint',
|
|
42229
|
+
material: sub,
|
|
42230
|
+
length: 8,
|
|
42231
|
+
});
|
|
42232
|
+
if (!systemId.startsWith(`${expectedPrefix}-`)) {
|
|
42233
|
+
logger$3.warning('oauth2_attach_node_identity_mismatch', {
|
|
42234
|
+
system_id: systemId,
|
|
42235
|
+
expected_prefix: expectedPrefix,
|
|
42236
|
+
subject: sub,
|
|
42237
|
+
});
|
|
42238
|
+
return false;
|
|
42239
|
+
}
|
|
42240
|
+
logger$3.debug('oauth2_attach_node_identity_verified', {
|
|
42241
|
+
system_id: systemId,
|
|
42242
|
+
expected_prefix: expectedPrefix,
|
|
42243
|
+
});
|
|
42244
|
+
return true;
|
|
42245
|
+
}
|
|
42198
42246
|
}
|
|
42199
42247
|
|
|
42200
42248
|
var oauth2Authorizer = /*#__PURE__*/Object.freeze({
|
|
@@ -23,6 +23,8 @@ export interface OAuth2AuthorizerConfig extends AuthorizerConfig {
|
|
|
23
23
|
token_issuer_config?: TokenIssuerConfig;
|
|
24
24
|
reverseAuthTtlSec?: number;
|
|
25
25
|
reverse_auth_ttl_sec?: number;
|
|
26
|
+
enforceTokenSubjectNodeIdentity?: boolean;
|
|
27
|
+
enforce_token_subject_node_identity?: boolean;
|
|
26
28
|
}
|
|
27
29
|
export declare const FACTORY_META: {
|
|
28
30
|
readonly base: "AuthorizerFactory";
|
|
@@ -14,6 +14,7 @@ export interface OAuth2AuthorizerOptions {
|
|
|
14
14
|
defaultTtlSec?: number;
|
|
15
15
|
maxTtlSec?: number;
|
|
16
16
|
reverseAuthTtlSec?: number;
|
|
17
|
+
enforceTokenSubjectNodeIdentity?: boolean;
|
|
17
18
|
}
|
|
18
19
|
export declare class OAuth2Authorizer implements Authorizer, TokenVerifierProvider, NodeEventListener {
|
|
19
20
|
readonly priority = 1000;
|
|
@@ -23,6 +24,7 @@ export declare class OAuth2Authorizer implements Authorizer, TokenVerifierProvid
|
|
|
23
24
|
private readonly requiredScopes;
|
|
24
25
|
private readonly requireScope;
|
|
25
26
|
private readonly reverseAuthTtlSec;
|
|
27
|
+
private readonly enforceTokenSubjectNodeIdentity;
|
|
26
28
|
private node?;
|
|
27
29
|
constructor(rawOptions: OAuth2AuthorizerOptions | Record<string, unknown>);
|
|
28
30
|
get tokenVerifier(): TokenVerifier;
|
|
@@ -35,4 +37,5 @@ export declare class OAuth2Authorizer implements Authorizer, TokenVerifierProvid
|
|
|
35
37
|
private extractScopes;
|
|
36
38
|
private mergeScopes;
|
|
37
39
|
private hasRequiredScope;
|
|
40
|
+
private validateTokenSubjectNodeIdentity;
|
|
38
41
|
}
|
package/dist/types/version.d.ts
CHANGED