@naylence/runtime 0.3.5-test.911 → 0.3.5-test.914
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 +78 -166
- package/dist/browser/index.mjs +78 -166
- package/dist/cjs/naylence/fame/config/extended-fame-config.js +58 -2
- package/dist/cjs/naylence/fame/http/jwks-api-router.js +16 -18
- package/dist/cjs/naylence/fame/http/oauth2-server.js +28 -31
- package/dist/cjs/naylence/fame/http/oauth2-token-router.js +153 -8
- package/dist/cjs/naylence/fame/http/openid-configuration-router.js +30 -32
- package/dist/cjs/naylence/fame/node/admission/admission-profile-factory.js +18 -0
- package/dist/cjs/naylence/fame/security/crypto/providers/default-crypto-provider.js +0 -162
- package/dist/cjs/version.js +2 -2
- package/dist/esm/naylence/fame/config/extended-fame-config.js +58 -2
- package/dist/esm/naylence/fame/http/jwks-api-router.js +16 -17
- package/dist/esm/naylence/fame/http/oauth2-server.js +28 -31
- package/dist/esm/naylence/fame/http/oauth2-token-router.js +153 -8
- package/dist/esm/naylence/fame/http/openid-configuration-router.js +30 -31
- package/dist/esm/naylence/fame/node/admission/admission-profile-factory.js +18 -0
- package/dist/esm/naylence/fame/security/crypto/providers/default-crypto-provider.js +0 -162
- package/dist/esm/version.js +2 -2
- package/dist/node/index.cjs +78 -166
- package/dist/node/index.mjs +78 -166
- package/dist/node/node.cjs +305 -251
- package/dist/node/node.mjs +305 -251
- package/dist/types/naylence/fame/http/jwks-api-router.d.ts +8 -8
- package/dist/types/naylence/fame/http/oauth2-server.d.ts +3 -3
- package/dist/types/naylence/fame/http/oauth2-token-router.d.ts +5 -5
- package/dist/types/naylence/fame/http/openid-configuration-router.d.ts +8 -8
- package/dist/types/naylence/fame/security/crypto/providers/default-crypto-provider.d.ts +0 -1
- package/dist/types/version.d.ts +1 -1
- package/package.json +4 -6
- package/dist/esm/naylence/fame/fastapi/oauth2-server.js +0 -205
- package/dist/types/naylence/fame/fastapi/oauth2-server.d.ts +0 -22
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OpenID Connect Discovery configuration
|
|
2
|
+
* OpenID Connect Discovery configuration plugin for Fastify
|
|
3
3
|
*
|
|
4
4
|
* Provides /.well-known/openid-configuration endpoint for OAuth2/OIDC client auto-discovery
|
|
5
5
|
*/
|
|
6
|
-
import express from 'express';
|
|
7
6
|
import { getLogger } from '../util/logging.js';
|
|
8
7
|
const logger = getLogger('naylence.fame.http.openid_configuration_router');
|
|
9
8
|
const DEFAULT_PREFIX = '';
|
|
@@ -77,10 +76,10 @@ function getAllowedScopes(configScopes) {
|
|
|
77
76
|
return configScopes ?? ['node.connect'];
|
|
78
77
|
}
|
|
79
78
|
/**
|
|
80
|
-
* Create
|
|
79
|
+
* Create a Fastify plugin that implements OpenID Connect Discovery
|
|
81
80
|
*
|
|
82
81
|
* @param options - Router configuration options
|
|
83
|
-
* @returns
|
|
82
|
+
* @returns Fastify plugin with OpenID configuration endpoint
|
|
84
83
|
*
|
|
85
84
|
* Environment Variables:
|
|
86
85
|
* FAME_JWT_ISSUER: JWT issuer claim (optional)
|
|
@@ -89,17 +88,16 @@ function getAllowedScopes(configScopes) {
|
|
|
89
88
|
*
|
|
90
89
|
* @example
|
|
91
90
|
* ```typescript
|
|
92
|
-
* import
|
|
91
|
+
* import Fastify from 'fastify';
|
|
93
92
|
* import { createOpenIDConfigurationRouter } from '@naylence/runtime';
|
|
94
93
|
*
|
|
95
|
-
* const app =
|
|
96
|
-
* app.
|
|
94
|
+
* const app = Fastify();
|
|
95
|
+
* app.register(createOpenIDConfigurationRouter({
|
|
97
96
|
* issuer: 'https://auth.example.com',
|
|
98
97
|
* }));
|
|
99
98
|
* ```
|
|
100
99
|
*/
|
|
101
100
|
export function createOpenIDConfigurationRouter(options = {}) {
|
|
102
|
-
const router = express.Router();
|
|
103
101
|
const { prefix = DEFAULT_PREFIX, issuer, baseUrl, tokenEndpointPath = '/oauth/token', jwksEndpointPath = '/.well-known/jwks.json', allowedScopes: configAllowedScopes, algorithm: configAlgorithm, } = normalizeOpenIDConfigurationRouterOptions(options);
|
|
104
102
|
// Resolve configuration with environment variable priority
|
|
105
103
|
const defaultIssuer = process.env[ENV_VAR_JWT_ISSUER] ?? issuer ?? 'https://auth.fame.fabric';
|
|
@@ -115,27 +113,28 @@ export function createOpenIDConfigurationRouter(options = {}) {
|
|
|
115
113
|
algorithm,
|
|
116
114
|
allowedScopes,
|
|
117
115
|
});
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
116
|
+
const plugin = async (instance) => {
|
|
117
|
+
instance.get(`${prefix}/.well-known/openid-configuration`, async (_request, reply) => {
|
|
118
|
+
// Construct absolute URLs for endpoints
|
|
119
|
+
const tokenEndpoint = `${defaultBaseUrl.replace(/\/$/, '')}${tokenEndpointPath}`;
|
|
120
|
+
const jwksUri = `${defaultBaseUrl.replace(/\/$/, '')}${jwksEndpointPath}`;
|
|
121
|
+
const config = {
|
|
122
|
+
issuer: defaultIssuer,
|
|
123
|
+
token_endpoint: tokenEndpoint,
|
|
124
|
+
jwks_uri: jwksUri,
|
|
125
|
+
scopes_supported: allowedScopes,
|
|
126
|
+
response_types_supported: ['token'],
|
|
127
|
+
grant_types_supported: ['client_credentials'],
|
|
128
|
+
token_endpoint_auth_methods_supported: [
|
|
129
|
+
'client_secret_basic',
|
|
130
|
+
'client_secret_post',
|
|
131
|
+
],
|
|
132
|
+
subject_types_supported: ['public'],
|
|
133
|
+
id_token_signing_alg_values_supported: [algorithm],
|
|
134
|
+
};
|
|
135
|
+
logger.debug('openid_config_served', { config });
|
|
136
|
+
reply.send(config);
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
return plugin;
|
|
141
140
|
}
|
|
@@ -19,6 +19,8 @@ const ENV_VAR_DIRECT_INPAGE_CHANNEL = 'FAME_DIRECT_INPAGE_CHANNEL';
|
|
|
19
19
|
const ENV_VAR_ADMISSION_SERVICE_URL = 'FAME_ADMISSION_SERVICE_URL';
|
|
20
20
|
const DEFAULT_INPAGE_CHANNEL = 'naylence-fabric';
|
|
21
21
|
const PROFILE_NAME_WELCOME = 'welcome';
|
|
22
|
+
const PROFILE_NAME_WELCOME_PKCE = 'welcome-pkce';
|
|
23
|
+
const PROFILE_NAME_WELCOME_PKCE_ALIAS = 'welcome_pkce';
|
|
22
24
|
const PROFILE_NAME_DIRECT = 'direct';
|
|
23
25
|
const PROFILE_NAME_DIRECT_HTTP = 'direct-http';
|
|
24
26
|
const PROFILE_NAME_DIRECT_INPAGE = 'direct-inpage';
|
|
@@ -79,6 +81,7 @@ function createOAuthPkceTokenProviderConfig() {
|
|
|
79
81
|
}
|
|
80
82
|
const welcomeIsRoot = Expressions.env(ENV_VAR_IS_ROOT, 'false');
|
|
81
83
|
const welcomeTokenProvider = createOAuthTokenProviderConfig();
|
|
84
|
+
const welcomePkceTokenProvider = createOAuthPkceTokenProviderConfig();
|
|
82
85
|
const WELCOME_SERVICE_PROFILE = {
|
|
83
86
|
type: 'WelcomeServiceClient',
|
|
84
87
|
is_root: welcomeIsRoot,
|
|
@@ -92,6 +95,19 @@ const WELCOME_SERVICE_PROFILE = {
|
|
|
92
95
|
tokenProvider: welcomeTokenProvider,
|
|
93
96
|
},
|
|
94
97
|
};
|
|
98
|
+
const WELCOME_SERVICE_PKCE_PROFILE = {
|
|
99
|
+
type: 'WelcomeServiceClient',
|
|
100
|
+
is_root: welcomeIsRoot,
|
|
101
|
+
isRoot: welcomeIsRoot,
|
|
102
|
+
url: Expressions.env(ENV_VAR_ADMISSION_SERVICE_URL),
|
|
103
|
+
supported_transports: ['websocket'],
|
|
104
|
+
supportedTransports: ['websocket'],
|
|
105
|
+
auth: {
|
|
106
|
+
type: 'BearerTokenHeaderAuth',
|
|
107
|
+
token_provider: welcomePkceTokenProvider,
|
|
108
|
+
tokenProvider: welcomePkceTokenProvider,
|
|
109
|
+
},
|
|
110
|
+
};
|
|
95
111
|
const directGrantTokenProvider = createOAuthTokenProviderConfig();
|
|
96
112
|
const directGrant = {
|
|
97
113
|
type: 'WebSocketConnectionGrant',
|
|
@@ -197,6 +213,8 @@ const NOOP_PROFILE = {
|
|
|
197
213
|
};
|
|
198
214
|
const PROFILE_MAP = {
|
|
199
215
|
[PROFILE_NAME_WELCOME]: WELCOME_SERVICE_PROFILE,
|
|
216
|
+
[PROFILE_NAME_WELCOME_PKCE]: WELCOME_SERVICE_PKCE_PROFILE,
|
|
217
|
+
[PROFILE_NAME_WELCOME_PKCE_ALIAS]: WELCOME_SERVICE_PKCE_PROFILE,
|
|
200
218
|
[PROFILE_NAME_DIRECT]: DIRECT_PROFILE,
|
|
201
219
|
[PROFILE_NAME_DIRECT_PKCE]: DIRECT_PKCE_PROFILE,
|
|
202
220
|
[PROFILE_NAME_DIRECT_PKCE_ALIAS]: DIRECT_PKCE_PROFILE,
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { AsnConvert, OctetString } from '@peculiar/asn1-schema';
|
|
2
|
-
import { AlgorithmIdentifier, Attribute, AttributeTypeAndValue, AttributeValue, Extension, Extensions, GeneralName, Name, RelativeDistinguishedName, SubjectAlternativeName, SubjectPublicKeyInfo, id_ce_subjectAltName, } from '@peculiar/asn1-x509';
|
|
3
|
-
import { Attributes, CertificationRequest, CertificationRequestInfo, } from '@peculiar/asn1-csr';
|
|
4
1
|
import { generateId } from '@naylence/core';
|
|
5
2
|
import { getLogger } from '../../../util/logging.js';
|
|
6
3
|
import { secureDigest } from '../../../util/util.js';
|
|
@@ -16,11 +13,6 @@ const DEFAULT_AUDIENCE = 'router-dev';
|
|
|
16
13
|
const DEFAULT_TTL_SEC = 3600;
|
|
17
14
|
const DEFAULT_HMAC_SECRET_BYTES = 32;
|
|
18
15
|
const ENCRYPTION_ALG = 'ECDH-ES';
|
|
19
|
-
const EXTENSION_REQUEST_OID = '1.2.840.113549.1.9.14';
|
|
20
|
-
const COMMON_NAME_OID = '2.5.4.3';
|
|
21
|
-
const ED25519_OID = '1.3.101.112';
|
|
22
|
-
const CSR_PEM_TAG = 'CERTIFICATE REQUEST';
|
|
23
|
-
const LOGICAL_URI_PREFIX = 'naylence://';
|
|
24
16
|
function normalizeDefaultCryptoProviderOptions(options) {
|
|
25
17
|
if (!options) {
|
|
26
18
|
return {};
|
|
@@ -286,76 +278,6 @@ export class DefaultCryptoProvider {
|
|
|
286
278
|
has_chain: Boolean(certificateChainPem),
|
|
287
279
|
});
|
|
288
280
|
}
|
|
289
|
-
async createCsr(nodeId, physicalPath, logicals, subjectName) {
|
|
290
|
-
const trimmedNodeId = assertNonEmptyString(nodeId, 'nodeId');
|
|
291
|
-
const trimmedPhysicalPath = assertNonEmptyString(physicalPath, 'physicalPath');
|
|
292
|
-
try {
|
|
293
|
-
if (this.artifacts.signing.algorithm !== 'EdDSA') {
|
|
294
|
-
throw new Error('CSR creation only supported for Ed25519 signing keys in the default crypto provider');
|
|
295
|
-
}
|
|
296
|
-
const cryptoImpl = await ensureWebCrypto();
|
|
297
|
-
const privateKey = await cryptoImpl.subtle.importKey('pkcs8', pemToArrayBuffer(this.signingPrivatePem), {
|
|
298
|
-
name: 'Ed25519',
|
|
299
|
-
}, false, ['sign']);
|
|
300
|
-
const publicKeyDer = pemToArrayBuffer(this.signingPublicPem);
|
|
301
|
-
const subjectPkInfo = AsnConvert.parse(publicKeyDer, SubjectPublicKeyInfo);
|
|
302
|
-
const sanitizedLogicals = Array.isArray(logicals)
|
|
303
|
-
? logicals.filter((value) => typeof value === 'string' && value.trim().length > 0)
|
|
304
|
-
: [];
|
|
305
|
-
const commonName = typeof subjectName === 'string' && subjectName.trim().length > 0
|
|
306
|
-
? subjectName.trim()
|
|
307
|
-
: trimmedNodeId;
|
|
308
|
-
const subject = buildSubjectName(commonName);
|
|
309
|
-
const attributes = new Attributes();
|
|
310
|
-
if (sanitizedLogicals.length > 0) {
|
|
311
|
-
const san = new SubjectAlternativeName(sanitizedLogicals.map((logical) => new GeneralName({
|
|
312
|
-
uniformResourceIdentifier: `${LOGICAL_URI_PREFIX}${logical}`,
|
|
313
|
-
})));
|
|
314
|
-
const extensions = new Extensions([
|
|
315
|
-
new Extension({
|
|
316
|
-
extnID: id_ce_subjectAltName,
|
|
317
|
-
critical: false,
|
|
318
|
-
extnValue: new OctetString(AsnConvert.serialize(san)),
|
|
319
|
-
}),
|
|
320
|
-
]);
|
|
321
|
-
attributes.push(new Attribute({
|
|
322
|
-
type: EXTENSION_REQUEST_OID,
|
|
323
|
-
values: [AsnConvert.serialize(extensions)],
|
|
324
|
-
}));
|
|
325
|
-
}
|
|
326
|
-
const requestInfo = new CertificationRequestInfo({
|
|
327
|
-
subject,
|
|
328
|
-
subjectPKInfo: subjectPkInfo,
|
|
329
|
-
attributes,
|
|
330
|
-
});
|
|
331
|
-
const requestInfoDer = AsnConvert.serialize(requestInfo);
|
|
332
|
-
const signature = await cryptoImpl.subtle.sign('Ed25519', privateKey, requestInfoDer);
|
|
333
|
-
const certificationRequest = new CertificationRequest({
|
|
334
|
-
certificationRequestInfo: requestInfo,
|
|
335
|
-
signatureAlgorithm: new AlgorithmIdentifier({
|
|
336
|
-
algorithm: ED25519_OID,
|
|
337
|
-
}),
|
|
338
|
-
signature: encodeBitString(signature),
|
|
339
|
-
});
|
|
340
|
-
certificationRequest.certificationRequestInfoRaw = requestInfoDer;
|
|
341
|
-
const csrDer = AsnConvert.serialize(certificationRequest);
|
|
342
|
-
const csrPem = arrayBufferToPem(csrDer, CSR_PEM_TAG);
|
|
343
|
-
logger.debug('csr_created', {
|
|
344
|
-
node_id: trimmedNodeId,
|
|
345
|
-
physical_path: trimmedPhysicalPath,
|
|
346
|
-
logical_count: sanitizedLogicals.length,
|
|
347
|
-
});
|
|
348
|
-
return csrPem;
|
|
349
|
-
}
|
|
350
|
-
catch (error) {
|
|
351
|
-
logger.error('csr_creation_failed', {
|
|
352
|
-
node_id: trimmedNodeId,
|
|
353
|
-
physical_path: trimmedPhysicalPath,
|
|
354
|
-
error: error instanceof Error ? error.message : String(error),
|
|
355
|
-
});
|
|
356
|
-
throw error;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
281
|
}
|
|
360
282
|
async function buildProviderArtifacts(options) {
|
|
361
283
|
const algorithm = normalizeAlgorithm(options.algorithm ?? readEnvAlgorithm());
|
|
@@ -591,90 +513,6 @@ function pemToDerBase64(pem) {
|
|
|
591
513
|
// Ensure the output is valid base64 without whitespace
|
|
592
514
|
return base64.replace(/\s+/g, '');
|
|
593
515
|
}
|
|
594
|
-
let cryptoPromise = null;
|
|
595
|
-
async function ensureWebCrypto() {
|
|
596
|
-
if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto?.subtle) {
|
|
597
|
-
return globalThis.crypto;
|
|
598
|
-
}
|
|
599
|
-
if (!cryptoPromise) {
|
|
600
|
-
if (typeof process !== 'undefined' &&
|
|
601
|
-
typeof process.versions?.node === 'string') {
|
|
602
|
-
cryptoPromise = import('node:crypto').then((module) => {
|
|
603
|
-
const webcrypto = module.webcrypto;
|
|
604
|
-
if (!webcrypto || !webcrypto.subtle) {
|
|
605
|
-
throw new Error('WebCrypto API is not available in this Node.js runtime');
|
|
606
|
-
}
|
|
607
|
-
globalThis.crypto = webcrypto;
|
|
608
|
-
return webcrypto;
|
|
609
|
-
});
|
|
610
|
-
}
|
|
611
|
-
else {
|
|
612
|
-
cryptoPromise = Promise.reject(new Error('WebCrypto API is not available in this environment'));
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
return cryptoPromise;
|
|
616
|
-
}
|
|
617
|
-
function pemToArrayBuffer(pem) {
|
|
618
|
-
const normalized = pem
|
|
619
|
-
.replace(/-----BEGIN[^-]+-----/g, '')
|
|
620
|
-
.replace(/-----END[^-]+-----/g, '')
|
|
621
|
-
.replace(/\s+/g, '');
|
|
622
|
-
const bytes = base64ToBytes(normalized);
|
|
623
|
-
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
624
|
-
}
|
|
625
|
-
function base64ToBytes(base64) {
|
|
626
|
-
if (typeof Buffer !== 'undefined') {
|
|
627
|
-
const buffer = Buffer.from(base64, 'base64');
|
|
628
|
-
const bytes = new Uint8Array(buffer.length);
|
|
629
|
-
for (let i = 0; i < buffer.length; i += 1) {
|
|
630
|
-
bytes[i] = buffer[i];
|
|
631
|
-
}
|
|
632
|
-
return bytes;
|
|
633
|
-
}
|
|
634
|
-
if (typeof atob === 'function') {
|
|
635
|
-
const binary = atob(base64);
|
|
636
|
-
const bytes = new Uint8Array(binary.length);
|
|
637
|
-
for (let i = 0; i < binary.length; i += 1) {
|
|
638
|
-
bytes[i] = binary.charCodeAt(i);
|
|
639
|
-
}
|
|
640
|
-
return bytes;
|
|
641
|
-
}
|
|
642
|
-
throw new Error('No base64 decoder available in this environment');
|
|
643
|
-
}
|
|
644
|
-
function arrayBufferToPem(buffer, tag) {
|
|
645
|
-
const base64 = bytesToBase64(new Uint8Array(buffer));
|
|
646
|
-
return `-----BEGIN ${tag}-----\n${formatPem(base64)}\n-----END ${tag}-----\n`;
|
|
647
|
-
}
|
|
648
|
-
function formatPem(base64) {
|
|
649
|
-
const lines = [];
|
|
650
|
-
for (let i = 0; i < base64.length; i += 64) {
|
|
651
|
-
lines.push(base64.slice(i, i + 64));
|
|
652
|
-
}
|
|
653
|
-
return lines.join('\n');
|
|
654
|
-
}
|
|
655
|
-
function encodeBitString(signature) {
|
|
656
|
-
const bytes = new Uint8Array(signature);
|
|
657
|
-
const bitString = new Uint8Array(bytes.length + 1);
|
|
658
|
-
bitString.set(bytes, 1);
|
|
659
|
-
return bitString.buffer;
|
|
660
|
-
}
|
|
661
|
-
function buildSubjectName(commonName) {
|
|
662
|
-
const attribute = new AttributeTypeAndValue({
|
|
663
|
-
type: COMMON_NAME_OID,
|
|
664
|
-
value: new AttributeValue({ utf8String: commonName }),
|
|
665
|
-
});
|
|
666
|
-
return new Name([new RelativeDistinguishedName([attribute])]);
|
|
667
|
-
}
|
|
668
|
-
function assertNonEmptyString(value, name) {
|
|
669
|
-
if (typeof value !== 'string') {
|
|
670
|
-
throw new TypeError(`${name} must be a string`);
|
|
671
|
-
}
|
|
672
|
-
const trimmed = value.trim();
|
|
673
|
-
if (trimmed.length === 0) {
|
|
674
|
-
throw new TypeError(`${name} must be a non-empty string`);
|
|
675
|
-
}
|
|
676
|
-
return trimmed;
|
|
677
|
-
}
|
|
678
516
|
function cloneJson(value) {
|
|
679
517
|
return JSON.parse(JSON.stringify(value));
|
|
680
518
|
}
|
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.5-test.
|
|
2
|
+
// Generated from package.json version: 0.3.5-test.914
|
|
3
3
|
/**
|
|
4
4
|
* The package version, injected at build time.
|
|
5
5
|
* @internal
|
|
6
6
|
*/
|
|
7
|
-
export const VERSION = '0.3.5-test.
|
|
7
|
+
export const VERSION = '0.3.5-test.914';
|
package/dist/node/index.cjs
CHANGED
|
@@ -8,21 +8,18 @@ var ed25519_js = require('@noble/curves/ed25519.js');
|
|
|
8
8
|
var hkdf_js = require('@noble/hashes/hkdf.js');
|
|
9
9
|
var sha2_js = require('@noble/hashes/sha2.js');
|
|
10
10
|
var utils_js = require('@noble/hashes/utils.js');
|
|
11
|
-
var asn1Schema = require('@peculiar/asn1-schema');
|
|
12
|
-
var asn1X509 = require('@peculiar/asn1-x509');
|
|
13
|
-
var asn1Csr = require('@peculiar/asn1-csr');
|
|
14
11
|
var yaml = require('yaml');
|
|
15
12
|
var fastify = require('fastify');
|
|
16
13
|
var websocketPlugin = require('@fastify/websocket');
|
|
17
14
|
var ed25519 = require('@noble/ed25519');
|
|
18
15
|
|
|
19
16
|
// This file is auto-generated during build - do not edit manually
|
|
20
|
-
// Generated from package.json version: 0.3.5-test.
|
|
17
|
+
// Generated from package.json version: 0.3.5-test.914
|
|
21
18
|
/**
|
|
22
19
|
* The package version, injected at build time.
|
|
23
20
|
* @internal
|
|
24
21
|
*/
|
|
25
|
-
const VERSION = '0.3.5-test.
|
|
22
|
+
const VERSION = '0.3.5-test.914';
|
|
26
23
|
|
|
27
24
|
/**
|
|
28
25
|
* Fame protocol specific error classes with WebSocket close codes and proper inheritance.
|
|
@@ -13009,6 +13006,61 @@ const CONFIG_SEARCH_PATHS = [
|
|
|
13009
13006
|
];
|
|
13010
13007
|
const fsModuleSpecifier = String.fromCharCode(102) + String.fromCharCode(115);
|
|
13011
13008
|
let cachedFsModule = null;
|
|
13009
|
+
// Capture this module's URL without triggering TypeScript's import.meta restriction on CJS builds
|
|
13010
|
+
const currentModuleUrl = (() => {
|
|
13011
|
+
try {
|
|
13012
|
+
return (0, eval)('import.meta.url');
|
|
13013
|
+
}
|
|
13014
|
+
catch {
|
|
13015
|
+
return undefined;
|
|
13016
|
+
}
|
|
13017
|
+
})();
|
|
13018
|
+
let cachedNodeRequire = typeof require === 'function' ? require : null;
|
|
13019
|
+
function fileUrlToPath(url) {
|
|
13020
|
+
try {
|
|
13021
|
+
const parsed = new URL(url);
|
|
13022
|
+
if (parsed.protocol !== 'file:') {
|
|
13023
|
+
return null;
|
|
13024
|
+
}
|
|
13025
|
+
let pathname = parsed.pathname;
|
|
13026
|
+
if (typeof process !== 'undefined' &&
|
|
13027
|
+
process.platform === 'win32' &&
|
|
13028
|
+
pathname.startsWith('/')) {
|
|
13029
|
+
pathname = pathname.slice(1);
|
|
13030
|
+
}
|
|
13031
|
+
return decodeURIComponent(pathname);
|
|
13032
|
+
}
|
|
13033
|
+
catch {
|
|
13034
|
+
return null;
|
|
13035
|
+
}
|
|
13036
|
+
}
|
|
13037
|
+
function getNodeRequire() {
|
|
13038
|
+
if (cachedNodeRequire) {
|
|
13039
|
+
return cachedNodeRequire;
|
|
13040
|
+
}
|
|
13041
|
+
if (!isNode) {
|
|
13042
|
+
return null;
|
|
13043
|
+
}
|
|
13044
|
+
const processBinding = process.binding;
|
|
13045
|
+
if (typeof processBinding !== 'function') {
|
|
13046
|
+
return null;
|
|
13047
|
+
}
|
|
13048
|
+
try {
|
|
13049
|
+
const moduleWrap = processBinding('module_wrap');
|
|
13050
|
+
if (typeof moduleWrap?.createRequire !== 'function') {
|
|
13051
|
+
return null;
|
|
13052
|
+
}
|
|
13053
|
+
const modulePathFromUrl = currentModuleUrl
|
|
13054
|
+
? fileUrlToPath(currentModuleUrl)
|
|
13055
|
+
: null;
|
|
13056
|
+
const requireSource = modulePathFromUrl ?? `${process.cwd()}/.naylence-require-shim.js`;
|
|
13057
|
+
cachedNodeRequire = moduleWrap.createRequire(requireSource);
|
|
13058
|
+
return cachedNodeRequire;
|
|
13059
|
+
}
|
|
13060
|
+
catch {
|
|
13061
|
+
return null;
|
|
13062
|
+
}
|
|
13063
|
+
}
|
|
13012
13064
|
function getFsModule() {
|
|
13013
13065
|
if (cachedFsModule) {
|
|
13014
13066
|
return cachedFsModule;
|
|
@@ -13016,9 +13068,10 @@ function getFsModule() {
|
|
|
13016
13068
|
if (!isNode) {
|
|
13017
13069
|
throw new Error('File system access is not available in this environment');
|
|
13018
13070
|
}
|
|
13019
|
-
|
|
13071
|
+
const nodeRequire = typeof require === 'function' ? require : getNodeRequire();
|
|
13072
|
+
if (nodeRequire) {
|
|
13020
13073
|
try {
|
|
13021
|
-
cachedFsModule =
|
|
13074
|
+
cachedFsModule = nodeRequire(fsModuleSpecifier);
|
|
13022
13075
|
return cachedFsModule;
|
|
13023
13076
|
}
|
|
13024
13077
|
catch (error) {
|
|
@@ -25394,11 +25447,6 @@ const DEFAULT_AUDIENCE = 'router-dev';
|
|
|
25394
25447
|
const DEFAULT_TTL_SEC$1 = 3600;
|
|
25395
25448
|
const DEFAULT_HMAC_SECRET_BYTES = 32;
|
|
25396
25449
|
const ENCRYPTION_ALG = 'ECDH-ES';
|
|
25397
|
-
const EXTENSION_REQUEST_OID = '1.2.840.113549.1.9.14';
|
|
25398
|
-
const COMMON_NAME_OID = '2.5.4.3';
|
|
25399
|
-
const ED25519_OID = '1.3.101.112';
|
|
25400
|
-
const CSR_PEM_TAG = 'CERTIFICATE REQUEST';
|
|
25401
|
-
const LOGICAL_URI_PREFIX = 'naylence://';
|
|
25402
25450
|
function normalizeDefaultCryptoProviderOptions(options) {
|
|
25403
25451
|
if (!options) {
|
|
25404
25452
|
return {};
|
|
@@ -25664,76 +25712,6 @@ class DefaultCryptoProvider {
|
|
|
25664
25712
|
has_chain: Boolean(certificateChainPem),
|
|
25665
25713
|
});
|
|
25666
25714
|
}
|
|
25667
|
-
async createCsr(nodeId, physicalPath, logicals, subjectName) {
|
|
25668
|
-
const trimmedNodeId = assertNonEmptyString(nodeId, 'nodeId');
|
|
25669
|
-
const trimmedPhysicalPath = assertNonEmptyString(physicalPath, 'physicalPath');
|
|
25670
|
-
try {
|
|
25671
|
-
if (this.artifacts.signing.algorithm !== 'EdDSA') {
|
|
25672
|
-
throw new Error('CSR creation only supported for Ed25519 signing keys in the default crypto provider');
|
|
25673
|
-
}
|
|
25674
|
-
const cryptoImpl = await ensureWebCrypto();
|
|
25675
|
-
const privateKey = await cryptoImpl.subtle.importKey('pkcs8', pemToArrayBuffer(this.signingPrivatePem), {
|
|
25676
|
-
name: 'Ed25519',
|
|
25677
|
-
}, false, ['sign']);
|
|
25678
|
-
const publicKeyDer = pemToArrayBuffer(this.signingPublicPem);
|
|
25679
|
-
const subjectPkInfo = asn1Schema.AsnConvert.parse(publicKeyDer, asn1X509.SubjectPublicKeyInfo);
|
|
25680
|
-
const sanitizedLogicals = Array.isArray(logicals)
|
|
25681
|
-
? logicals.filter((value) => typeof value === 'string' && value.trim().length > 0)
|
|
25682
|
-
: [];
|
|
25683
|
-
const commonName = typeof subjectName === 'string' && subjectName.trim().length > 0
|
|
25684
|
-
? subjectName.trim()
|
|
25685
|
-
: trimmedNodeId;
|
|
25686
|
-
const subject = buildSubjectName(commonName);
|
|
25687
|
-
const attributes = new asn1Csr.Attributes();
|
|
25688
|
-
if (sanitizedLogicals.length > 0) {
|
|
25689
|
-
const san = new asn1X509.SubjectAlternativeName(sanitizedLogicals.map((logical) => new asn1X509.GeneralName({
|
|
25690
|
-
uniformResourceIdentifier: `${LOGICAL_URI_PREFIX}${logical}`,
|
|
25691
|
-
})));
|
|
25692
|
-
const extensions = new asn1X509.Extensions([
|
|
25693
|
-
new asn1X509.Extension({
|
|
25694
|
-
extnID: asn1X509.id_ce_subjectAltName,
|
|
25695
|
-
critical: false,
|
|
25696
|
-
extnValue: new asn1Schema.OctetString(asn1Schema.AsnConvert.serialize(san)),
|
|
25697
|
-
}),
|
|
25698
|
-
]);
|
|
25699
|
-
attributes.push(new asn1X509.Attribute({
|
|
25700
|
-
type: EXTENSION_REQUEST_OID,
|
|
25701
|
-
values: [asn1Schema.AsnConvert.serialize(extensions)],
|
|
25702
|
-
}));
|
|
25703
|
-
}
|
|
25704
|
-
const requestInfo = new asn1Csr.CertificationRequestInfo({
|
|
25705
|
-
subject,
|
|
25706
|
-
subjectPKInfo: subjectPkInfo,
|
|
25707
|
-
attributes,
|
|
25708
|
-
});
|
|
25709
|
-
const requestInfoDer = asn1Schema.AsnConvert.serialize(requestInfo);
|
|
25710
|
-
const signature = await cryptoImpl.subtle.sign('Ed25519', privateKey, requestInfoDer);
|
|
25711
|
-
const certificationRequest = new asn1Csr.CertificationRequest({
|
|
25712
|
-
certificationRequestInfo: requestInfo,
|
|
25713
|
-
signatureAlgorithm: new asn1X509.AlgorithmIdentifier({
|
|
25714
|
-
algorithm: ED25519_OID,
|
|
25715
|
-
}),
|
|
25716
|
-
signature: encodeBitString(signature),
|
|
25717
|
-
});
|
|
25718
|
-
certificationRequest.certificationRequestInfoRaw = requestInfoDer;
|
|
25719
|
-
const csrDer = asn1Schema.AsnConvert.serialize(certificationRequest);
|
|
25720
|
-
const csrPem = arrayBufferToPem(csrDer, CSR_PEM_TAG);
|
|
25721
|
-
logger$v.debug('csr_created', {
|
|
25722
|
-
node_id: trimmedNodeId,
|
|
25723
|
-
physical_path: trimmedPhysicalPath,
|
|
25724
|
-
logical_count: sanitizedLogicals.length,
|
|
25725
|
-
});
|
|
25726
|
-
return csrPem;
|
|
25727
|
-
}
|
|
25728
|
-
catch (error) {
|
|
25729
|
-
logger$v.error('csr_creation_failed', {
|
|
25730
|
-
node_id: trimmedNodeId,
|
|
25731
|
-
physical_path: trimmedPhysicalPath,
|
|
25732
|
-
error: error instanceof Error ? error.message : String(error),
|
|
25733
|
-
});
|
|
25734
|
-
throw error;
|
|
25735
|
-
}
|
|
25736
|
-
}
|
|
25737
25715
|
}
|
|
25738
25716
|
async function buildProviderArtifacts(options) {
|
|
25739
25717
|
const algorithm = normalizeAlgorithm(options.algorithm ?? readEnvAlgorithm());
|
|
@@ -25969,90 +25947,6 @@ function pemToDerBase64(pem) {
|
|
|
25969
25947
|
// Ensure the output is valid base64 without whitespace
|
|
25970
25948
|
return base64.replace(/\s+/g, '');
|
|
25971
25949
|
}
|
|
25972
|
-
let cryptoPromise = null;
|
|
25973
|
-
async function ensureWebCrypto() {
|
|
25974
|
-
if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto?.subtle) {
|
|
25975
|
-
return globalThis.crypto;
|
|
25976
|
-
}
|
|
25977
|
-
if (!cryptoPromise) {
|
|
25978
|
-
if (typeof process !== 'undefined' &&
|
|
25979
|
-
typeof process.versions?.node === 'string') {
|
|
25980
|
-
cryptoPromise = import('node:crypto').then((module) => {
|
|
25981
|
-
const webcrypto = module.webcrypto;
|
|
25982
|
-
if (!webcrypto || !webcrypto.subtle) {
|
|
25983
|
-
throw new Error('WebCrypto API is not available in this Node.js runtime');
|
|
25984
|
-
}
|
|
25985
|
-
globalThis.crypto = webcrypto;
|
|
25986
|
-
return webcrypto;
|
|
25987
|
-
});
|
|
25988
|
-
}
|
|
25989
|
-
else {
|
|
25990
|
-
cryptoPromise = Promise.reject(new Error('WebCrypto API is not available in this environment'));
|
|
25991
|
-
}
|
|
25992
|
-
}
|
|
25993
|
-
return cryptoPromise;
|
|
25994
|
-
}
|
|
25995
|
-
function pemToArrayBuffer(pem) {
|
|
25996
|
-
const normalized = pem
|
|
25997
|
-
.replace(/-----BEGIN[^-]+-----/g, '')
|
|
25998
|
-
.replace(/-----END[^-]+-----/g, '')
|
|
25999
|
-
.replace(/\s+/g, '');
|
|
26000
|
-
const bytes = base64ToBytes$1(normalized);
|
|
26001
|
-
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
26002
|
-
}
|
|
26003
|
-
function base64ToBytes$1(base64) {
|
|
26004
|
-
if (typeof Buffer !== 'undefined') {
|
|
26005
|
-
const buffer = Buffer.from(base64, 'base64');
|
|
26006
|
-
const bytes = new Uint8Array(buffer.length);
|
|
26007
|
-
for (let i = 0; i < buffer.length; i += 1) {
|
|
26008
|
-
bytes[i] = buffer[i];
|
|
26009
|
-
}
|
|
26010
|
-
return bytes;
|
|
26011
|
-
}
|
|
26012
|
-
if (typeof atob === 'function') {
|
|
26013
|
-
const binary = atob(base64);
|
|
26014
|
-
const bytes = new Uint8Array(binary.length);
|
|
26015
|
-
for (let i = 0; i < binary.length; i += 1) {
|
|
26016
|
-
bytes[i] = binary.charCodeAt(i);
|
|
26017
|
-
}
|
|
26018
|
-
return bytes;
|
|
26019
|
-
}
|
|
26020
|
-
throw new Error('No base64 decoder available in this environment');
|
|
26021
|
-
}
|
|
26022
|
-
function arrayBufferToPem(buffer, tag) {
|
|
26023
|
-
const base64 = bytesToBase64(new Uint8Array(buffer));
|
|
26024
|
-
return `-----BEGIN ${tag}-----\n${formatPem(base64)}\n-----END ${tag}-----\n`;
|
|
26025
|
-
}
|
|
26026
|
-
function formatPem(base64) {
|
|
26027
|
-
const lines = [];
|
|
26028
|
-
for (let i = 0; i < base64.length; i += 64) {
|
|
26029
|
-
lines.push(base64.slice(i, i + 64));
|
|
26030
|
-
}
|
|
26031
|
-
return lines.join('\n');
|
|
26032
|
-
}
|
|
26033
|
-
function encodeBitString(signature) {
|
|
26034
|
-
const bytes = new Uint8Array(signature);
|
|
26035
|
-
const bitString = new Uint8Array(bytes.length + 1);
|
|
26036
|
-
bitString.set(bytes, 1);
|
|
26037
|
-
return bitString.buffer;
|
|
26038
|
-
}
|
|
26039
|
-
function buildSubjectName(commonName) {
|
|
26040
|
-
const attribute = new asn1X509.AttributeTypeAndValue({
|
|
26041
|
-
type: COMMON_NAME_OID,
|
|
26042
|
-
value: new asn1X509.AttributeValue({ utf8String: commonName }),
|
|
26043
|
-
});
|
|
26044
|
-
return new asn1X509.Name([new asn1X509.RelativeDistinguishedName([attribute])]);
|
|
26045
|
-
}
|
|
26046
|
-
function assertNonEmptyString(value, name) {
|
|
26047
|
-
if (typeof value !== 'string') {
|
|
26048
|
-
throw new TypeError(`${name} must be a string`);
|
|
26049
|
-
}
|
|
26050
|
-
const trimmed = value.trim();
|
|
26051
|
-
if (trimmed.length === 0) {
|
|
26052
|
-
throw new TypeError(`${name} must be a non-empty string`);
|
|
26053
|
-
}
|
|
26054
|
-
return trimmed;
|
|
26055
|
-
}
|
|
26056
25950
|
function cloneJson(value) {
|
|
26057
25951
|
return JSON.parse(JSON.stringify(value));
|
|
26058
25952
|
}
|
|
@@ -30500,6 +30394,8 @@ const ENV_VAR_DIRECT_INPAGE_CHANNEL = 'FAME_DIRECT_INPAGE_CHANNEL';
|
|
|
30500
30394
|
const ENV_VAR_ADMISSION_SERVICE_URL = 'FAME_ADMISSION_SERVICE_URL';
|
|
30501
30395
|
const DEFAULT_INPAGE_CHANNEL = 'naylence-fabric';
|
|
30502
30396
|
const PROFILE_NAME_WELCOME = 'welcome';
|
|
30397
|
+
const PROFILE_NAME_WELCOME_PKCE = 'welcome-pkce';
|
|
30398
|
+
const PROFILE_NAME_WELCOME_PKCE_ALIAS = 'welcome_pkce';
|
|
30503
30399
|
const PROFILE_NAME_DIRECT = 'direct';
|
|
30504
30400
|
const PROFILE_NAME_DIRECT_HTTP = 'direct-http';
|
|
30505
30401
|
const PROFILE_NAME_DIRECT_INPAGE = 'direct-inpage';
|
|
@@ -30560,6 +30456,7 @@ function createOAuthPkceTokenProviderConfig() {
|
|
|
30560
30456
|
}
|
|
30561
30457
|
const welcomeIsRoot = factory.Expressions.env(ENV_VAR_IS_ROOT, 'false');
|
|
30562
30458
|
const welcomeTokenProvider = createOAuthTokenProviderConfig();
|
|
30459
|
+
const welcomePkceTokenProvider = createOAuthPkceTokenProviderConfig();
|
|
30563
30460
|
const WELCOME_SERVICE_PROFILE = {
|
|
30564
30461
|
type: 'WelcomeServiceClient',
|
|
30565
30462
|
is_root: welcomeIsRoot,
|
|
@@ -30573,6 +30470,19 @@ const WELCOME_SERVICE_PROFILE = {
|
|
|
30573
30470
|
tokenProvider: welcomeTokenProvider,
|
|
30574
30471
|
},
|
|
30575
30472
|
};
|
|
30473
|
+
const WELCOME_SERVICE_PKCE_PROFILE = {
|
|
30474
|
+
type: 'WelcomeServiceClient',
|
|
30475
|
+
is_root: welcomeIsRoot,
|
|
30476
|
+
isRoot: welcomeIsRoot,
|
|
30477
|
+
url: factory.Expressions.env(ENV_VAR_ADMISSION_SERVICE_URL),
|
|
30478
|
+
supported_transports: ['websocket'],
|
|
30479
|
+
supportedTransports: ['websocket'],
|
|
30480
|
+
auth: {
|
|
30481
|
+
type: 'BearerTokenHeaderAuth',
|
|
30482
|
+
token_provider: welcomePkceTokenProvider,
|
|
30483
|
+
tokenProvider: welcomePkceTokenProvider,
|
|
30484
|
+
},
|
|
30485
|
+
};
|
|
30576
30486
|
const directGrantTokenProvider = createOAuthTokenProviderConfig();
|
|
30577
30487
|
const directGrant = {
|
|
30578
30488
|
type: 'WebSocketConnectionGrant',
|
|
@@ -30678,6 +30588,8 @@ const NOOP_PROFILE = {
|
|
|
30678
30588
|
};
|
|
30679
30589
|
const PROFILE_MAP$1 = {
|
|
30680
30590
|
[PROFILE_NAME_WELCOME]: WELCOME_SERVICE_PROFILE,
|
|
30591
|
+
[PROFILE_NAME_WELCOME_PKCE]: WELCOME_SERVICE_PKCE_PROFILE,
|
|
30592
|
+
[PROFILE_NAME_WELCOME_PKCE_ALIAS]: WELCOME_SERVICE_PKCE_PROFILE,
|
|
30681
30593
|
[PROFILE_NAME_DIRECT]: DIRECT_PROFILE,
|
|
30682
30594
|
[PROFILE_NAME_DIRECT_PKCE]: DIRECT_PKCE_PROFILE,
|
|
30683
30595
|
[PROFILE_NAME_DIRECT_PKCE_ALIAS]: DIRECT_PKCE_PROFILE,
|