@monocloud/auth-core 0.1.7 → 0.1.9
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/index.cjs +318 -97
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +163 -35
- package/dist/index.mjs +318 -99
- package/dist/index.mjs.map +1 -1
- package/dist/{types-DmlJMcTH.d.mts → types-BVOv1R0s.d.mts} +169 -32
- package/dist/utils/index.cjs +1 -1
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.mts +1 -1
- package/dist/utils/index.mjs +2 -2
- package/dist/utils/index.mjs.map +1 -1
- package/dist/utils/internal.cjs +10 -0
- package/dist/utils/internal.cjs.map +1 -1
- package/dist/utils/internal.d.mts +11 -2
- package/dist/utils/internal.mjs +10 -1
- package/dist/utils/internal.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -598,12 +598,47 @@ interface MonoCloudSession {
|
|
|
598
598
|
*/
|
|
599
599
|
[key: string]: unknown;
|
|
600
600
|
}
|
|
601
|
+
/**
|
|
602
|
+
* Standard JWT claims shared between ID tokens and access tokens.
|
|
603
|
+
*
|
|
604
|
+
* @category Types
|
|
605
|
+
*/
|
|
606
|
+
interface JwtClaims {
|
|
607
|
+
/**
|
|
608
|
+
* Issuer identifier - the authorization server that issued the token.
|
|
609
|
+
*/
|
|
610
|
+
iss: string;
|
|
611
|
+
/**
|
|
612
|
+
* Subject identifier — uniquely identifies the authenticated user.
|
|
613
|
+
*/
|
|
614
|
+
sub: string;
|
|
615
|
+
/**
|
|
616
|
+
* Intended audience(s) of the token.
|
|
617
|
+
*/
|
|
618
|
+
aud: string | string[];
|
|
619
|
+
/**
|
|
620
|
+
* Expiration time of the token (Unix epoch seconds).
|
|
621
|
+
*/
|
|
622
|
+
exp: number;
|
|
623
|
+
/**
|
|
624
|
+
* Time at which the token was issued (Unix epoch seconds).
|
|
625
|
+
*/
|
|
626
|
+
iat: number;
|
|
627
|
+
/**
|
|
628
|
+
* Not-before time (Unix epoch seconds).
|
|
629
|
+
*/
|
|
630
|
+
nbf?: number;
|
|
631
|
+
/**
|
|
632
|
+
* Additional custom or provider-specific claims.
|
|
633
|
+
*/
|
|
634
|
+
[key: string]: unknown;
|
|
635
|
+
}
|
|
601
636
|
/**
|
|
602
637
|
* Standard OpenID Connect ID Token claims.
|
|
603
638
|
*
|
|
604
639
|
* @category Types
|
|
605
640
|
*/
|
|
606
|
-
interface IdTokenClaims extends UserinfoResponse {
|
|
641
|
+
interface IdTokenClaims extends UserinfoResponse, JwtClaims {
|
|
607
642
|
/**
|
|
608
643
|
* Authentication Context Class Reference. Indicates the assurance level of the authentication performed.
|
|
609
644
|
*/
|
|
@@ -616,10 +651,6 @@ interface IdTokenClaims extends UserinfoResponse {
|
|
|
616
651
|
* Access token hash. Used to validate access tokens returned alongside the ID token.
|
|
617
652
|
*/
|
|
618
653
|
at_hash?: string;
|
|
619
|
-
/**
|
|
620
|
-
* Intended audience(s) of the ID token.
|
|
621
|
-
*/
|
|
622
|
-
aud: string | string[];
|
|
623
654
|
/**
|
|
624
655
|
* Time when the end-user authentication occurred (Unix epoch seconds).
|
|
625
656
|
*/
|
|
@@ -632,18 +663,6 @@ interface IdTokenClaims extends UserinfoResponse {
|
|
|
632
663
|
* Authorization code hash. Used to validate authorization codes returned with hybrid flows.
|
|
633
664
|
*/
|
|
634
665
|
c_hash?: string;
|
|
635
|
-
/**
|
|
636
|
-
* Expiration time of the ID token (Unix epoch seconds).
|
|
637
|
-
*/
|
|
638
|
-
exp: number;
|
|
639
|
-
/**
|
|
640
|
-
* Time at which the ID token was issued (Unix epoch seconds).
|
|
641
|
-
*/
|
|
642
|
-
iat: number;
|
|
643
|
-
/**
|
|
644
|
-
* Issuer identifier - the authorization server that issued the token.
|
|
645
|
-
*/
|
|
646
|
-
iss: string;
|
|
647
666
|
/**
|
|
648
667
|
* Nonce value used to associate the authentication request with the issued ID token and prevent replay attacks.
|
|
649
668
|
*/
|
|
@@ -652,14 +671,25 @@ interface IdTokenClaims extends UserinfoResponse {
|
|
|
652
671
|
* State hash (used in some hybrid flow validations).
|
|
653
672
|
*/
|
|
654
673
|
s_hash?: string;
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Claims contained in a validated OAuth 2.0 access token.
|
|
677
|
+
*
|
|
678
|
+
* @category Types
|
|
679
|
+
*/
|
|
680
|
+
interface AccessTokenClaims extends JwtClaims {
|
|
655
681
|
/**
|
|
656
|
-
*
|
|
682
|
+
* OAuth scope associated with the token.
|
|
657
683
|
*/
|
|
658
|
-
|
|
684
|
+
scope?: string;
|
|
659
685
|
/**
|
|
660
|
-
*
|
|
686
|
+
* Client ID of the application the token was issued to.
|
|
661
687
|
*/
|
|
662
|
-
|
|
688
|
+
client_id?: string;
|
|
689
|
+
/**
|
|
690
|
+
* JWT ID (unique identifier for the token).
|
|
691
|
+
*/
|
|
692
|
+
jti?: string;
|
|
663
693
|
}
|
|
664
694
|
/**
|
|
665
695
|
* OAuth 2.0 / OpenID Connect token endpoint response.
|
|
@@ -1165,7 +1195,15 @@ type ClientAuthMethod =
|
|
|
1165
1195
|
/**
|
|
1166
1196
|
* Client authenticates using a signed JWT created with a private key.
|
|
1167
1197
|
*/
|
|
1168
|
-
| 'private_key_jwt'
|
|
1198
|
+
| 'private_key_jwt'
|
|
1199
|
+
/**
|
|
1200
|
+
* Client authenticates using a TLS client certificate issued by a trusted certificate authority.
|
|
1201
|
+
*/
|
|
1202
|
+
| 'tls_client_auth'
|
|
1203
|
+
/**
|
|
1204
|
+
* Client authenticates using a self-signed TLS client certificate.
|
|
1205
|
+
*/
|
|
1206
|
+
| 'self_signed_tls_client_auth';
|
|
1169
1207
|
/**
|
|
1170
1208
|
* Parameters used when creating a Pushed Authorization Request (PAR).
|
|
1171
1209
|
*
|
|
@@ -1177,13 +1215,16 @@ type ClientAuthMethod =
|
|
|
1177
1215
|
*/
|
|
1178
1216
|
interface PushedAuthorizationParams extends Omit<AuthorizationParams, 'requestUri'> {}
|
|
1179
1217
|
/**
|
|
1180
|
-
*
|
|
1218
|
+
* Shared configuration options for MonoCloud OIDC clients.
|
|
1219
|
+
*
|
|
1220
|
+
* These options are common to both {@link MonoCloudOidcClientOptions}
|
|
1221
|
+
* and {@link MonoCloudOidcBackendClientOptions}.
|
|
1181
1222
|
*
|
|
1182
1223
|
* @category Types
|
|
1183
1224
|
*/
|
|
1184
|
-
interface
|
|
1225
|
+
interface MonoCloudClientOptionsBase {
|
|
1185
1226
|
/**
|
|
1186
|
-
* Client secret used for client authentication.
|
|
1227
|
+
* Client secret or key material used for client authentication.
|
|
1187
1228
|
*
|
|
1188
1229
|
* When `clientAuthMethod` is `client_secret_jwt` and a plain-text secret is provided, the default signing algorithm is `HS256`.
|
|
1189
1230
|
*
|
|
@@ -1192,13 +1233,9 @@ interface MonoCloudClientOptions {
|
|
|
1192
1233
|
clientSecret?: string | Jwk;
|
|
1193
1234
|
/**
|
|
1194
1235
|
* Client authentication method used when communicating with the token endpoint.
|
|
1236
|
+
* @defaultValue 'client_secret_basic'
|
|
1195
1237
|
*/
|
|
1196
1238
|
clientAuthMethod?: ClientAuthMethod;
|
|
1197
|
-
/**
|
|
1198
|
-
* Expected signing algorithm for validating ID tokens.
|
|
1199
|
-
* @defaultValue 'RS256'
|
|
1200
|
-
*/
|
|
1201
|
-
idTokenSigningAlgorithm?: SecurityAlgorithms;
|
|
1202
1239
|
/**
|
|
1203
1240
|
* Duration (in seconds) to cache the JSON Web Key Set (JWKS) retrieved from the authorization server.
|
|
1204
1241
|
* @defaultValue 300
|
|
@@ -1209,6 +1246,65 @@ interface MonoCloudClientOptions {
|
|
|
1209
1246
|
* @defaultValue 300
|
|
1210
1247
|
*/
|
|
1211
1248
|
metadataCacheDuration?: number;
|
|
1249
|
+
/**
|
|
1250
|
+
* Optional custom `fetch` implementation used for network requests.
|
|
1251
|
+
*/
|
|
1252
|
+
fetcher?: typeof fetch;
|
|
1253
|
+
}
|
|
1254
|
+
/**
|
|
1255
|
+
* Configuration options used to initialize the MonoCloudOidcClient.
|
|
1256
|
+
*
|
|
1257
|
+
* @category Types
|
|
1258
|
+
*/
|
|
1259
|
+
interface MonoCloudOidcClientOptions extends MonoCloudClientOptionsBase {
|
|
1260
|
+
/**
|
|
1261
|
+
* Expected signing algorithm for validating ID tokens.
|
|
1262
|
+
* @defaultValue 'RS256'
|
|
1263
|
+
*/
|
|
1264
|
+
idTokenSigningAlgorithm?: SecurityAlgorithms;
|
|
1265
|
+
}
|
|
1266
|
+
/**
|
|
1267
|
+
* Options for configuring group membership validation on access tokens.
|
|
1268
|
+
*
|
|
1269
|
+
* @category Types
|
|
1270
|
+
*/
|
|
1271
|
+
interface IsUserInGroupOptions {
|
|
1272
|
+
/**
|
|
1273
|
+
* The claim name in the token that contains group memberships.
|
|
1274
|
+
* @defaultValue 'groups'
|
|
1275
|
+
*/
|
|
1276
|
+
groupsClaim?: string;
|
|
1277
|
+
/**
|
|
1278
|
+
* When `true`, requires the token to contain all specified groups.
|
|
1279
|
+
* When `false`, requires at least one of the specified groups.
|
|
1280
|
+
* @defaultValue false
|
|
1281
|
+
*/
|
|
1282
|
+
matchAll?: boolean;
|
|
1283
|
+
}
|
|
1284
|
+
/**
|
|
1285
|
+
* Configuration options used to initialize the MonoCloudOidcBackendClient.
|
|
1286
|
+
*
|
|
1287
|
+
* @category Types
|
|
1288
|
+
*/
|
|
1289
|
+
interface MonoCloudOidcBackendClientOptions extends MonoCloudClientOptionsBase {
|
|
1290
|
+
/**
|
|
1291
|
+
* Client identifier of the application registered in MonoCloud.
|
|
1292
|
+
*/
|
|
1293
|
+
clientId?: string;
|
|
1294
|
+
/**
|
|
1295
|
+
* Number of seconds to adjust the current time to account for clock differences.
|
|
1296
|
+
* @defaultValue 0
|
|
1297
|
+
*/
|
|
1298
|
+
clockSkew?: number;
|
|
1299
|
+
/**
|
|
1300
|
+
* Additional time tolerance in seconds for time-based claim validation.
|
|
1301
|
+
* @defaultValue 300
|
|
1302
|
+
*/
|
|
1303
|
+
clockTolerance?: number;
|
|
1304
|
+
/**
|
|
1305
|
+
* Options for group membership validation applied to all token validations performed by this client.
|
|
1306
|
+
*/
|
|
1307
|
+
groupOptions?: IsUserInGroupOptions;
|
|
1212
1308
|
}
|
|
1213
1309
|
/**
|
|
1214
1310
|
* Response returned from the Pushed Authorization Request (PAR) endpoint.
|
|
@@ -1252,6 +1348,47 @@ idToken?: Partial<IdTokenClaims>,
|
|
|
1252
1348
|
* Optional. Claims returned from the UserInfo endpoint.
|
|
1253
1349
|
*/
|
|
1254
1350
|
userInfo?: UserinfoResponse) => Promise<void> | void;
|
|
1351
|
+
/**
|
|
1352
|
+
* Shared options for token validation and introspection.
|
|
1353
|
+
* @category Types
|
|
1354
|
+
*/
|
|
1355
|
+
interface TokenValidationOptionsBase {
|
|
1356
|
+
/**
|
|
1357
|
+
* List of scopes that must all be present in the token's `scope` claim.
|
|
1358
|
+
*/
|
|
1359
|
+
scopes?: string[];
|
|
1360
|
+
/**
|
|
1361
|
+
* List of group names or identifiers that must be present in the token's groups claim.
|
|
1362
|
+
*/
|
|
1363
|
+
groups?: string[];
|
|
1364
|
+
/**
|
|
1365
|
+
* PEM-encoded client certificate used for certificate-bound token validation.
|
|
1366
|
+
*/
|
|
1367
|
+
clientCertificate?: string;
|
|
1368
|
+
/**
|
|
1369
|
+
* When `true`, validates certificate binding for certificate-bound access tokens.
|
|
1370
|
+
*
|
|
1371
|
+
* @defaultValue false
|
|
1372
|
+
*/
|
|
1373
|
+
validateCertificateBinding?: boolean;
|
|
1374
|
+
}
|
|
1375
|
+
/**
|
|
1376
|
+
* Options for validating a JWT access token.
|
|
1377
|
+
*
|
|
1378
|
+
* @category Types
|
|
1379
|
+
*/
|
|
1380
|
+
interface ValidateJwtAccessTokenOptions extends TokenValidationOptionsBase {
|
|
1381
|
+
/**
|
|
1382
|
+
* Pre-fetched JSON Web Key Set to use for signature verification instead of fetching from the server.
|
|
1383
|
+
*/
|
|
1384
|
+
jwks?: Jwks;
|
|
1385
|
+
}
|
|
1386
|
+
/**
|
|
1387
|
+
* Options for introspecting an opaque access token.
|
|
1388
|
+
*
|
|
1389
|
+
* @category Types
|
|
1390
|
+
*/
|
|
1391
|
+
interface IntrospectOptions extends TokenValidationOptionsBase {}
|
|
1255
1392
|
//#endregion
|
|
1256
|
-
export {
|
|
1257
|
-
//# sourceMappingURL=types-
|
|
1393
|
+
export { PushedAuthorizationParams as A, ValidateJwtAccessTokenOptions as B, MonoCloudOidcBackendClientOptions as C, OnSessionCreating as D, MonoCloudUser as E, ResponseTypes as F, SecurityAlgorithms as I, TokenValidationOptionsBase as L, RefreshGrantOptions as M, RefreshSessionOptions as N, ParResponse as O, ResponseModes as P, Tokens as R, MonoCloudClientOptionsBase as S, MonoCloudSession as T, IssuerMetadata as _, AuthenticateOptions as a, JwsHeaderParameters as b, CallbackParams as c, DisplayOptions as d, EndSessionParameters as f, IsUserInGroupOptions as g, IntrospectOptions as h, AuthState as i, RefetchUserInfoOptions as j, Prompt as k, ClientAuthMethod as l, IdTokenClaims as m, AccessTokenClaims as n, Authenticators as o, Group as p, Address as r, AuthorizationParams as s, AccessToken as t, CodeChallengeMethod as u, Jwk as v, MonoCloudOidcClientOptions as w, JwtClaims as x, Jwks as y, UserinfoResponse as z };
|
|
1394
|
+
//# sourceMappingURL=types-BVOv1R0s.d.mts.map
|
package/dist/utils/index.cjs
CHANGED
|
@@ -205,7 +205,7 @@ const generatePKCE = async () => {
|
|
|
205
205
|
const codeVerifier = require_utils_internal.randomBytes(32);
|
|
206
206
|
return {
|
|
207
207
|
codeVerifier,
|
|
208
|
-
codeChallenge:
|
|
208
|
+
codeChallenge: await require_utils_internal.sha256(codeVerifier)
|
|
209
209
|
};
|
|
210
210
|
};
|
|
211
211
|
/**
|
package/dist/utils/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["stringToArrayBuffer","arrayBufferToBase64","fromB64Url","arrayBufferToString","now","randomBytes","encodeBase64Url"],"sources":["../../src/utils/index.ts"],"sourcesContent":["import type {\n AuthState,\n CallbackParams,\n IdTokenClaims,\n MonoCloudSession,\n MonoCloudUser,\n} from '../types';\nimport {\n arrayBufferToBase64,\n arrayBufferToString,\n encodeBase64Url,\n fromB64Url,\n now,\n randomBytes,\n stringToArrayBuffer,\n} from './internal';\n\nconst PBKDF2_ITERATIONS = 310_000;\nconst SALT_LENGTH = 16;\nconst GCM_IV_LENGTH = 12;\n\nconst deriveEncryptionKey = async (\n secret: string,\n salt: Uint8Array\n): Promise<CryptoKey> => {\n const baseKey = await crypto.subtle.importKey(\n 'raw',\n stringToArrayBuffer(secret) as BufferSource,\n 'PBKDF2',\n false,\n ['deriveKey']\n );\n\n return crypto.subtle.deriveKey(\n {\n name: 'PBKDF2',\n salt: salt as BufferSource,\n iterations: PBKDF2_ITERATIONS,\n hash: 'SHA-256',\n },\n baseKey,\n { name: 'AES-GCM', length: 256 },\n false,\n ['encrypt', 'decrypt']\n );\n};\n\n/**\n * Parses callback parameters from a URL, a URLSearchParams object, or a query string.\n */\nexport const parseCallbackParams = (\n queryOrUrl: string | URL | URLSearchParams\n): CallbackParams => {\n let params;\n\n if (queryOrUrl instanceof URL) {\n params = queryOrUrl.searchParams;\n } else if (queryOrUrl instanceof URLSearchParams) {\n params = queryOrUrl;\n } else {\n try {\n params = new URL(queryOrUrl).searchParams;\n } catch {\n // eslint-disable-next-line no-param-reassign\n queryOrUrl =\n queryOrUrl.startsWith('?') || queryOrUrl.startsWith('#')\n ? queryOrUrl.substring(1)\n : queryOrUrl;\n params = new URLSearchParams(queryOrUrl);\n }\n }\n\n const expiresIn = params.get('expires_in');\n\n return {\n state: params.get('state') ?? undefined,\n accessToken: params.get('access_token') ?? undefined,\n idToken: params.get('id_token') ?? undefined,\n refreshToken: params.get('refresh_token') ?? undefined,\n sessionState: params.get('session_state') ?? undefined,\n expiresIn: expiresIn ? parseInt(expiresIn, 10) : undefined,\n code: params.get('code') ?? undefined,\n error: params.get('error') ?? undefined,\n errorDescription: params.get('error_description') ?? undefined,\n };\n};\n\n/**\n * Encrypts a given string using a secret with AES-GCM.\n *\n * @param data - The plaintext data to encrypt.\n * @param secret - The secret used to derive the encryption key.\n * @returns Base64-encoded ciphertext.\n */\nexport const encrypt = async (\n data: string,\n secret: string\n): Promise<string> => {\n const salt = crypto.getRandomValues(new Uint8Array(SALT_LENGTH));\n const iv = crypto.getRandomValues(new Uint8Array(GCM_IV_LENGTH));\n const plaintextBuffer = stringToArrayBuffer(data);\n const key = await deriveEncryptionKey(secret, salt);\n\n const ciphertext = await crypto.subtle.encrypt(\n {\n name: 'AES-GCM',\n iv,\n },\n key,\n plaintextBuffer as BufferSource\n );\n\n const resultBuffer = new Uint8Array(\n salt.byteLength + iv.byteLength + ciphertext.byteLength\n );\n resultBuffer.set(salt, 0);\n resultBuffer.set(iv, salt.byteLength);\n resultBuffer.set(new Uint8Array(ciphertext), salt.byteLength + iv.byteLength);\n\n return arrayBufferToBase64(resultBuffer);\n};\n\n/**\n * Decrypts an encrypted string using a secret with AES-GCM.\n *\n * @param encrypted - The ciphertext to decrypt.\n * @param secret - The secret used to derive the decryption key.\n *\n * @returns Decrypted plaintext string or undefined if decryption fails.\n */\nexport const decrypt = async (\n encrypted: string,\n secret: string\n): Promise<string | undefined> => {\n try {\n const ciphertextBuffer = Uint8Array.from(atob(fromB64Url(encrypted)), c =>\n c.charCodeAt(0)\n );\n\n if (ciphertextBuffer.byteLength <= SALT_LENGTH + GCM_IV_LENGTH) {\n return undefined;\n }\n\n const salt = ciphertextBuffer.slice(0, SALT_LENGTH);\n const iv = ciphertextBuffer.slice(SALT_LENGTH, SALT_LENGTH + GCM_IV_LENGTH);\n const encryptedPayload = ciphertextBuffer.slice(\n SALT_LENGTH + GCM_IV_LENGTH\n );\n const key = await deriveEncryptionKey(secret, salt);\n const decryptedBuffer = await crypto.subtle.decrypt(\n {\n name: 'AES-GCM',\n iv,\n },\n key,\n encryptedPayload\n );\n return arrayBufferToString(decryptedBuffer);\n } catch {\n return undefined;\n }\n};\n\n/**\n * Encrypts a MonoCloud session object with a secret and optional time-to-live (TTL).\n *\n * @param session - The session object to encrypt.\n * @param secret - The secret used for encryption.\n * @param ttl - Optional time-to-live in seconds, after which the session expires.\n * @returns Encrypted session string.\n */\nexport const encryptSession = (\n session: MonoCloudSession,\n secret: string,\n ttl?: number\n): Promise<string> => {\n let expiresAt;\n\n if (typeof ttl === 'number') {\n expiresAt = now() + ttl;\n }\n return encrypt(JSON.stringify({ session, expiresAt }), secret);\n};\n\n/**\n * Decrypts an encrypted MonoCloud session.\n *\n * @param encryptedSession - The encrypted session string to decrypt.\n * @param secret - The secret used for decryption.\n *\n * @returns Session object on success.\n *\n * @throws If decryption fails or the session has expired.\n */\nexport const decryptSession = async (\n encryptedSession: string,\n secret: string\n): Promise<MonoCloudSession> => {\n const decryptedText = await decrypt(encryptedSession, secret);\n\n if (!decryptedText) {\n throw new Error('Invalid session data');\n }\n\n let payload: { session: MonoCloudSession; expiresAt?: number };\n try {\n payload = JSON.parse(decryptedText);\n } catch {\n throw new Error('Invalid session data');\n }\n\n const { session, expiresAt } = payload;\n\n if (!session) {\n throw new Error('Invalid session data');\n }\n\n if (typeof expiresAt === 'number' && expiresAt < now()) {\n throw new Error('Session Expired');\n }\n\n return session;\n};\n\n/**\n * Encrypts an AuthState object with a secret and optional time-to-live (TTL).\n *\n * @param authState - A type that extends the AuthState interface.\n * @param secret - The secret used for encryption.\n * @param ttl - Optional time-to-live in seconds, after which the auth state expires.\n *\n * @returns Encrypted auth state string.\n */\nexport const encryptAuthState = <T extends AuthState>(\n authState: T,\n secret: string,\n ttl?: number\n): Promise<string> => {\n let expiresAt;\n\n if (typeof ttl === 'number') {\n expiresAt = now() + ttl;\n }\n\n return encrypt(JSON.stringify({ authState, expiresAt }), secret);\n};\n\n/**\n * Decrypts an encrypted AuthState.\n *\n * @param encryptedAuthState - The encrypted auth state string to decrypt.\n * @param secret - The secret used for decryption.\n *\n * @returns State object on success.\n *\n * @throws If decryption fails or the auth state has expired.\n *\n */\nexport const decryptAuthState = async <T extends AuthState>(\n encryptedAuthState: string,\n secret: string\n): Promise<T> => {\n const decryptedText = await decrypt(encryptedAuthState, secret);\n\n if (!decryptedText) {\n throw new Error('Invalid auth state');\n }\n\n let payload: { authState: T; expiresAt?: number };\n try {\n payload = JSON.parse(decryptedText);\n } catch {\n throw new Error('Invalid auth state');\n }\n\n const { authState, expiresAt } = payload;\n\n if (!authState) {\n throw new Error('Invalid auth state');\n }\n\n if (typeof expiresAt === 'number' && expiresAt < now()) {\n throw new Error('Auth state expired');\n }\n\n return authState;\n};\n\n/**\n * Checks if a user is a member of a specified group or groups.\n *\n * @param user - The user.\n * @param groups - An array of group names or IDs to check membership against.\n * @param groupsClaim - The claim in the user object that contains groups.\n * @param matchAll - If `true`, requires the user to be in all specified groups; if `false`, checks if the user is in at least one of the groups.\n *\n * @returns `true` if the user is in the specified groups, `false` otherwise.\n */\nexport const isUserInGroup = (\n user: MonoCloudUser | IdTokenClaims,\n groups: string[],\n groupsClaim = 'groups',\n matchAll = false\n): boolean => {\n const userGroups = (user[groupsClaim] ?? []) as (\n | string\n | { id: string; name: string }\n )[];\n\n if (!Array.isArray(groups) || groups.length === 0) {\n return true;\n }\n\n if (!Array.isArray(userGroups) || userGroups.length === 0) {\n return false;\n }\n\n let matched = false;\n\n for (const expectedGroup of groups) {\n const userInGroup = userGroups.some(\n g =>\n (typeof g === 'string' && g === expectedGroup) ||\n (typeof g === 'object' &&\n (g.id === expectedGroup || g.name === expectedGroup))\n );\n\n if (!matchAll && userInGroup) {\n return userInGroup;\n }\n\n if (matchAll && !userInGroup) {\n return false;\n }\n\n matched = userInGroup;\n }\n\n return matched;\n};\n\n/**\n * Generates a random state string.\n */\nexport const generateState = (): string => randomBytes(32);\n\n/**\n * Generates a PKCE (Proof Key for Code Exchange) code verifier and code challenge.\n */\nexport const generatePKCE = async (): Promise<{\n codeVerifier: string;\n codeChallenge: string;\n}> => {\n const codeVerifier = randomBytes(32);\n return {\n codeVerifier,\n codeChallenge: encodeBase64Url(\n await crypto.subtle.digest(\n 'SHA-256',\n stringToArrayBuffer(codeVerifier) as BufferSource\n )\n ),\n };\n};\n\n/**\n * Generates a random nonce string.\n */\nexport const generateNonce = (): string => randomBytes(32);\n\n/**\n * @ignore\n * Merges multiple arrays of strings, removing duplicates.\n *\n * @param args - List of arrays to merge.\n *\n * @returns A new array containing unique strings from both input arrays, or `undefined` if both inputs are `undefined`.\n */\nexport const mergeArrays = (\n ...args: (string[] | undefined)[]\n): string[] | undefined => {\n const arrays = args.filter(x => Array.isArray(x));\n return arrays.length > 0\n ? Array.from(new Set(arrays.reduce((acc, x) => [...acc, ...x], [])))\n : undefined;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["stringToArrayBuffer","arrayBufferToBase64","fromB64Url","arrayBufferToString","now","randomBytes","sha256"],"sources":["../../src/utils/index.ts"],"sourcesContent":["import type {\n AuthState,\n CallbackParams,\n IdTokenClaims,\n MonoCloudSession,\n MonoCloudUser,\n} from '../types';\nimport {\n arrayBufferToBase64,\n arrayBufferToString,\n fromB64Url,\n now,\n randomBytes,\n sha256,\n stringToArrayBuffer,\n} from './internal';\n\nconst PBKDF2_ITERATIONS = 310_000;\nconst SALT_LENGTH = 16;\nconst GCM_IV_LENGTH = 12;\n\nconst deriveEncryptionKey = async (\n secret: string,\n salt: Uint8Array\n): Promise<CryptoKey> => {\n const baseKey = await crypto.subtle.importKey(\n 'raw',\n stringToArrayBuffer(secret) as BufferSource,\n 'PBKDF2',\n false,\n ['deriveKey']\n );\n\n return crypto.subtle.deriveKey(\n {\n name: 'PBKDF2',\n salt: salt as BufferSource,\n iterations: PBKDF2_ITERATIONS,\n hash: 'SHA-256',\n },\n baseKey,\n { name: 'AES-GCM', length: 256 },\n false,\n ['encrypt', 'decrypt']\n );\n};\n\n/**\n * Parses callback parameters from a URL, a URLSearchParams object, or a query string.\n */\nexport const parseCallbackParams = (\n queryOrUrl: string | URL | URLSearchParams\n): CallbackParams => {\n let params;\n\n if (queryOrUrl instanceof URL) {\n params = queryOrUrl.searchParams;\n } else if (queryOrUrl instanceof URLSearchParams) {\n params = queryOrUrl;\n } else {\n try {\n params = new URL(queryOrUrl).searchParams;\n } catch {\n // eslint-disable-next-line no-param-reassign\n queryOrUrl =\n queryOrUrl.startsWith('?') || queryOrUrl.startsWith('#')\n ? queryOrUrl.substring(1)\n : queryOrUrl;\n params = new URLSearchParams(queryOrUrl);\n }\n }\n\n const expiresIn = params.get('expires_in');\n\n return {\n state: params.get('state') ?? undefined,\n accessToken: params.get('access_token') ?? undefined,\n idToken: params.get('id_token') ?? undefined,\n refreshToken: params.get('refresh_token') ?? undefined,\n sessionState: params.get('session_state') ?? undefined,\n expiresIn: expiresIn ? parseInt(expiresIn, 10) : undefined,\n code: params.get('code') ?? undefined,\n error: params.get('error') ?? undefined,\n errorDescription: params.get('error_description') ?? undefined,\n };\n};\n\n/**\n * Encrypts a given string using a secret with AES-GCM.\n *\n * @param data - The plaintext data to encrypt.\n * @param secret - The secret used to derive the encryption key.\n * @returns Base64-encoded ciphertext.\n */\nexport const encrypt = async (\n data: string,\n secret: string\n): Promise<string> => {\n const salt = crypto.getRandomValues(new Uint8Array(SALT_LENGTH));\n const iv = crypto.getRandomValues(new Uint8Array(GCM_IV_LENGTH));\n const plaintextBuffer = stringToArrayBuffer(data);\n const key = await deriveEncryptionKey(secret, salt);\n\n const ciphertext = await crypto.subtle.encrypt(\n {\n name: 'AES-GCM',\n iv,\n },\n key,\n plaintextBuffer as BufferSource\n );\n\n const resultBuffer = new Uint8Array(\n salt.byteLength + iv.byteLength + ciphertext.byteLength\n );\n resultBuffer.set(salt, 0);\n resultBuffer.set(iv, salt.byteLength);\n resultBuffer.set(new Uint8Array(ciphertext), salt.byteLength + iv.byteLength);\n\n return arrayBufferToBase64(resultBuffer);\n};\n\n/**\n * Decrypts an encrypted string using a secret with AES-GCM.\n *\n * @param encrypted - The ciphertext to decrypt.\n * @param secret - The secret used to derive the decryption key.\n *\n * @returns Decrypted plaintext string or undefined if decryption fails.\n */\nexport const decrypt = async (\n encrypted: string,\n secret: string\n): Promise<string | undefined> => {\n try {\n const ciphertextBuffer = Uint8Array.from(atob(fromB64Url(encrypted)), c =>\n c.charCodeAt(0)\n );\n\n if (ciphertextBuffer.byteLength <= SALT_LENGTH + GCM_IV_LENGTH) {\n return undefined;\n }\n\n const salt = ciphertextBuffer.slice(0, SALT_LENGTH);\n const iv = ciphertextBuffer.slice(SALT_LENGTH, SALT_LENGTH + GCM_IV_LENGTH);\n const encryptedPayload = ciphertextBuffer.slice(\n SALT_LENGTH + GCM_IV_LENGTH\n );\n const key = await deriveEncryptionKey(secret, salt);\n const decryptedBuffer = await crypto.subtle.decrypt(\n {\n name: 'AES-GCM',\n iv,\n },\n key,\n encryptedPayload\n );\n return arrayBufferToString(decryptedBuffer);\n } catch {\n return undefined;\n }\n};\n\n/**\n * Encrypts a MonoCloud session object with a secret and optional time-to-live (TTL).\n *\n * @param session - The session object to encrypt.\n * @param secret - The secret used for encryption.\n * @param ttl - Optional time-to-live in seconds, after which the session expires.\n * @returns Encrypted session string.\n */\nexport const encryptSession = (\n session: MonoCloudSession,\n secret: string,\n ttl?: number\n): Promise<string> => {\n let expiresAt;\n\n if (typeof ttl === 'number') {\n expiresAt = now() + ttl;\n }\n return encrypt(JSON.stringify({ session, expiresAt }), secret);\n};\n\n/**\n * Decrypts an encrypted MonoCloud session.\n *\n * @param encryptedSession - The encrypted session string to decrypt.\n * @param secret - The secret used for decryption.\n *\n * @returns Session object on success.\n *\n * @throws If decryption fails or the session has expired.\n */\nexport const decryptSession = async (\n encryptedSession: string,\n secret: string\n): Promise<MonoCloudSession> => {\n const decryptedText = await decrypt(encryptedSession, secret);\n\n if (!decryptedText) {\n throw new Error('Invalid session data');\n }\n\n let payload: { session: MonoCloudSession; expiresAt?: number };\n try {\n payload = JSON.parse(decryptedText);\n } catch {\n throw new Error('Invalid session data');\n }\n\n const { session, expiresAt } = payload;\n\n if (!session) {\n throw new Error('Invalid session data');\n }\n\n if (typeof expiresAt === 'number' && expiresAt < now()) {\n throw new Error('Session Expired');\n }\n\n return session;\n};\n\n/**\n * Encrypts an AuthState object with a secret and optional time-to-live (TTL).\n *\n * @param authState - A type that extends the AuthState interface.\n * @param secret - The secret used for encryption.\n * @param ttl - Optional time-to-live in seconds, after which the auth state expires.\n *\n * @returns Encrypted auth state string.\n */\nexport const encryptAuthState = <T extends AuthState>(\n authState: T,\n secret: string,\n ttl?: number\n): Promise<string> => {\n let expiresAt;\n\n if (typeof ttl === 'number') {\n expiresAt = now() + ttl;\n }\n\n return encrypt(JSON.stringify({ authState, expiresAt }), secret);\n};\n\n/**\n * Decrypts an encrypted AuthState.\n *\n * @param encryptedAuthState - The encrypted auth state string to decrypt.\n * @param secret - The secret used for decryption.\n *\n * @returns State object on success.\n *\n * @throws If decryption fails or the auth state has expired.\n *\n */\nexport const decryptAuthState = async <T extends AuthState>(\n encryptedAuthState: string,\n secret: string\n): Promise<T> => {\n const decryptedText = await decrypt(encryptedAuthState, secret);\n\n if (!decryptedText) {\n throw new Error('Invalid auth state');\n }\n\n let payload: { authState: T; expiresAt?: number };\n try {\n payload = JSON.parse(decryptedText);\n } catch {\n throw new Error('Invalid auth state');\n }\n\n const { authState, expiresAt } = payload;\n\n if (!authState) {\n throw new Error('Invalid auth state');\n }\n\n if (typeof expiresAt === 'number' && expiresAt < now()) {\n throw new Error('Auth state expired');\n }\n\n return authState;\n};\n\n/**\n * Checks if a user is a member of a specified group or groups.\n *\n * @param user - The user.\n * @param groups - An array of group names or IDs to check membership against.\n * @param groupsClaim - The claim in the user object that contains groups.\n * @param matchAll - If `true`, requires the user to be in all specified groups; if `false`, checks if the user is in at least one of the groups.\n *\n * @returns `true` if the user is in the specified groups, `false` otherwise.\n */\nexport const isUserInGroup = (\n user: MonoCloudUser | IdTokenClaims,\n groups: string[],\n groupsClaim = 'groups',\n matchAll = false\n): boolean => {\n const userGroups = (user[groupsClaim] ?? []) as (\n | string\n | { id: string; name: string }\n )[];\n\n if (!Array.isArray(groups) || groups.length === 0) {\n return true;\n }\n\n if (!Array.isArray(userGroups) || userGroups.length === 0) {\n return false;\n }\n\n let matched = false;\n\n for (const expectedGroup of groups) {\n const userInGroup = userGroups.some(\n g =>\n (typeof g === 'string' && g === expectedGroup) ||\n (typeof g === 'object' &&\n (g.id === expectedGroup || g.name === expectedGroup))\n );\n\n if (!matchAll && userInGroup) {\n return userInGroup;\n }\n\n if (matchAll && !userInGroup) {\n return false;\n }\n\n matched = userInGroup;\n }\n\n return matched;\n};\n\n/**\n * Generates a random state string.\n */\nexport const generateState = (): string => randomBytes(32);\n\n/**\n * Generates a PKCE (Proof Key for Code Exchange) code verifier and code challenge.\n */\nexport const generatePKCE = async (): Promise<{\n codeVerifier: string;\n codeChallenge: string;\n}> => {\n const codeVerifier = randomBytes(32);\n return {\n codeVerifier,\n codeChallenge: await sha256(codeVerifier),\n };\n};\n\n/**\n * Generates a random nonce string.\n */\nexport const generateNonce = (): string => randomBytes(32);\n\n/**\n * @ignore\n * Merges multiple arrays of strings, removing duplicates.\n *\n * @param args - List of arrays to merge.\n *\n * @returns A new array containing unique strings from both input arrays, or `undefined` if both inputs are `undefined`.\n */\nexport const mergeArrays = (\n ...args: (string[] | undefined)[]\n): string[] | undefined => {\n const arrays = args.filter(x => Array.isArray(x));\n return arrays.length > 0\n ? Array.from(new Set(arrays.reduce((acc, x) => [...acc, ...x], [])))\n : undefined;\n};\n"],"mappings":"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"}
|
package/dist/utils/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { E as MonoCloudUser, T as MonoCloudSession, c as CallbackParams, i as AuthState, m as IdTokenClaims } from "../types-BVOv1R0s.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/utils/index.d.ts
|
|
4
4
|
/**
|
package/dist/utils/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { arrayBufferToBase64, arrayBufferToString,
|
|
1
|
+
import { arrayBufferToBase64, arrayBufferToString, fromB64Url, now, randomBytes, sha256, stringToArrayBuffer } from "./internal.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/utils/index.ts
|
|
4
4
|
const PBKDF2_ITERATIONS = 31e4;
|
|
@@ -204,7 +204,7 @@ const generatePKCE = async () => {
|
|
|
204
204
|
const codeVerifier = randomBytes(32);
|
|
205
205
|
return {
|
|
206
206
|
codeVerifier,
|
|
207
|
-
codeChallenge:
|
|
207
|
+
codeChallenge: await sha256(codeVerifier)
|
|
208
208
|
};
|
|
209
209
|
};
|
|
210
210
|
/**
|
package/dist/utils/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/utils/index.ts"],"sourcesContent":["import type {\n AuthState,\n CallbackParams,\n IdTokenClaims,\n MonoCloudSession,\n MonoCloudUser,\n} from '../types';\nimport {\n arrayBufferToBase64,\n arrayBufferToString,\n encodeBase64Url,\n fromB64Url,\n now,\n randomBytes,\n stringToArrayBuffer,\n} from './internal';\n\nconst PBKDF2_ITERATIONS = 310_000;\nconst SALT_LENGTH = 16;\nconst GCM_IV_LENGTH = 12;\n\nconst deriveEncryptionKey = async (\n secret: string,\n salt: Uint8Array\n): Promise<CryptoKey> => {\n const baseKey = await crypto.subtle.importKey(\n 'raw',\n stringToArrayBuffer(secret) as BufferSource,\n 'PBKDF2',\n false,\n ['deriveKey']\n );\n\n return crypto.subtle.deriveKey(\n {\n name: 'PBKDF2',\n salt: salt as BufferSource,\n iterations: PBKDF2_ITERATIONS,\n hash: 'SHA-256',\n },\n baseKey,\n { name: 'AES-GCM', length: 256 },\n false,\n ['encrypt', 'decrypt']\n );\n};\n\n/**\n * Parses callback parameters from a URL, a URLSearchParams object, or a query string.\n */\nexport const parseCallbackParams = (\n queryOrUrl: string | URL | URLSearchParams\n): CallbackParams => {\n let params;\n\n if (queryOrUrl instanceof URL) {\n params = queryOrUrl.searchParams;\n } else if (queryOrUrl instanceof URLSearchParams) {\n params = queryOrUrl;\n } else {\n try {\n params = new URL(queryOrUrl).searchParams;\n } catch {\n // eslint-disable-next-line no-param-reassign\n queryOrUrl =\n queryOrUrl.startsWith('?') || queryOrUrl.startsWith('#')\n ? queryOrUrl.substring(1)\n : queryOrUrl;\n params = new URLSearchParams(queryOrUrl);\n }\n }\n\n const expiresIn = params.get('expires_in');\n\n return {\n state: params.get('state') ?? undefined,\n accessToken: params.get('access_token') ?? undefined,\n idToken: params.get('id_token') ?? undefined,\n refreshToken: params.get('refresh_token') ?? undefined,\n sessionState: params.get('session_state') ?? undefined,\n expiresIn: expiresIn ? parseInt(expiresIn, 10) : undefined,\n code: params.get('code') ?? undefined,\n error: params.get('error') ?? undefined,\n errorDescription: params.get('error_description') ?? undefined,\n };\n};\n\n/**\n * Encrypts a given string using a secret with AES-GCM.\n *\n * @param data - The plaintext data to encrypt.\n * @param secret - The secret used to derive the encryption key.\n * @returns Base64-encoded ciphertext.\n */\nexport const encrypt = async (\n data: string,\n secret: string\n): Promise<string> => {\n const salt = crypto.getRandomValues(new Uint8Array(SALT_LENGTH));\n const iv = crypto.getRandomValues(new Uint8Array(GCM_IV_LENGTH));\n const plaintextBuffer = stringToArrayBuffer(data);\n const key = await deriveEncryptionKey(secret, salt);\n\n const ciphertext = await crypto.subtle.encrypt(\n {\n name: 'AES-GCM',\n iv,\n },\n key,\n plaintextBuffer as BufferSource\n );\n\n const resultBuffer = new Uint8Array(\n salt.byteLength + iv.byteLength + ciphertext.byteLength\n );\n resultBuffer.set(salt, 0);\n resultBuffer.set(iv, salt.byteLength);\n resultBuffer.set(new Uint8Array(ciphertext), salt.byteLength + iv.byteLength);\n\n return arrayBufferToBase64(resultBuffer);\n};\n\n/**\n * Decrypts an encrypted string using a secret with AES-GCM.\n *\n * @param encrypted - The ciphertext to decrypt.\n * @param secret - The secret used to derive the decryption key.\n *\n * @returns Decrypted plaintext string or undefined if decryption fails.\n */\nexport const decrypt = async (\n encrypted: string,\n secret: string\n): Promise<string | undefined> => {\n try {\n const ciphertextBuffer = Uint8Array.from(atob(fromB64Url(encrypted)), c =>\n c.charCodeAt(0)\n );\n\n if (ciphertextBuffer.byteLength <= SALT_LENGTH + GCM_IV_LENGTH) {\n return undefined;\n }\n\n const salt = ciphertextBuffer.slice(0, SALT_LENGTH);\n const iv = ciphertextBuffer.slice(SALT_LENGTH, SALT_LENGTH + GCM_IV_LENGTH);\n const encryptedPayload = ciphertextBuffer.slice(\n SALT_LENGTH + GCM_IV_LENGTH\n );\n const key = await deriveEncryptionKey(secret, salt);\n const decryptedBuffer = await crypto.subtle.decrypt(\n {\n name: 'AES-GCM',\n iv,\n },\n key,\n encryptedPayload\n );\n return arrayBufferToString(decryptedBuffer);\n } catch {\n return undefined;\n }\n};\n\n/**\n * Encrypts a MonoCloud session object with a secret and optional time-to-live (TTL).\n *\n * @param session - The session object to encrypt.\n * @param secret - The secret used for encryption.\n * @param ttl - Optional time-to-live in seconds, after which the session expires.\n * @returns Encrypted session string.\n */\nexport const encryptSession = (\n session: MonoCloudSession,\n secret: string,\n ttl?: number\n): Promise<string> => {\n let expiresAt;\n\n if (typeof ttl === 'number') {\n expiresAt = now() + ttl;\n }\n return encrypt(JSON.stringify({ session, expiresAt }), secret);\n};\n\n/**\n * Decrypts an encrypted MonoCloud session.\n *\n * @param encryptedSession - The encrypted session string to decrypt.\n * @param secret - The secret used for decryption.\n *\n * @returns Session object on success.\n *\n * @throws If decryption fails or the session has expired.\n */\nexport const decryptSession = async (\n encryptedSession: string,\n secret: string\n): Promise<MonoCloudSession> => {\n const decryptedText = await decrypt(encryptedSession, secret);\n\n if (!decryptedText) {\n throw new Error('Invalid session data');\n }\n\n let payload: { session: MonoCloudSession; expiresAt?: number };\n try {\n payload = JSON.parse(decryptedText);\n } catch {\n throw new Error('Invalid session data');\n }\n\n const { session, expiresAt } = payload;\n\n if (!session) {\n throw new Error('Invalid session data');\n }\n\n if (typeof expiresAt === 'number' && expiresAt < now()) {\n throw new Error('Session Expired');\n }\n\n return session;\n};\n\n/**\n * Encrypts an AuthState object with a secret and optional time-to-live (TTL).\n *\n * @param authState - A type that extends the AuthState interface.\n * @param secret - The secret used for encryption.\n * @param ttl - Optional time-to-live in seconds, after which the auth state expires.\n *\n * @returns Encrypted auth state string.\n */\nexport const encryptAuthState = <T extends AuthState>(\n authState: T,\n secret: string,\n ttl?: number\n): Promise<string> => {\n let expiresAt;\n\n if (typeof ttl === 'number') {\n expiresAt = now() + ttl;\n }\n\n return encrypt(JSON.stringify({ authState, expiresAt }), secret);\n};\n\n/**\n * Decrypts an encrypted AuthState.\n *\n * @param encryptedAuthState - The encrypted auth state string to decrypt.\n * @param secret - The secret used for decryption.\n *\n * @returns State object on success.\n *\n * @throws If decryption fails or the auth state has expired.\n *\n */\nexport const decryptAuthState = async <T extends AuthState>(\n encryptedAuthState: string,\n secret: string\n): Promise<T> => {\n const decryptedText = await decrypt(encryptedAuthState, secret);\n\n if (!decryptedText) {\n throw new Error('Invalid auth state');\n }\n\n let payload: { authState: T; expiresAt?: number };\n try {\n payload = JSON.parse(decryptedText);\n } catch {\n throw new Error('Invalid auth state');\n }\n\n const { authState, expiresAt } = payload;\n\n if (!authState) {\n throw new Error('Invalid auth state');\n }\n\n if (typeof expiresAt === 'number' && expiresAt < now()) {\n throw new Error('Auth state expired');\n }\n\n return authState;\n};\n\n/**\n * Checks if a user is a member of a specified group or groups.\n *\n * @param user - The user.\n * @param groups - An array of group names or IDs to check membership against.\n * @param groupsClaim - The claim in the user object that contains groups.\n * @param matchAll - If `true`, requires the user to be in all specified groups; if `false`, checks if the user is in at least one of the groups.\n *\n * @returns `true` if the user is in the specified groups, `false` otherwise.\n */\nexport const isUserInGroup = (\n user: MonoCloudUser | IdTokenClaims,\n groups: string[],\n groupsClaim = 'groups',\n matchAll = false\n): boolean => {\n const userGroups = (user[groupsClaim] ?? []) as (\n | string\n | { id: string; name: string }\n )[];\n\n if (!Array.isArray(groups) || groups.length === 0) {\n return true;\n }\n\n if (!Array.isArray(userGroups) || userGroups.length === 0) {\n return false;\n }\n\n let matched = false;\n\n for (const expectedGroup of groups) {\n const userInGroup = userGroups.some(\n g =>\n (typeof g === 'string' && g === expectedGroup) ||\n (typeof g === 'object' &&\n (g.id === expectedGroup || g.name === expectedGroup))\n );\n\n if (!matchAll && userInGroup) {\n return userInGroup;\n }\n\n if (matchAll && !userInGroup) {\n return false;\n }\n\n matched = userInGroup;\n }\n\n return matched;\n};\n\n/**\n * Generates a random state string.\n */\nexport const generateState = (): string => randomBytes(32);\n\n/**\n * Generates a PKCE (Proof Key for Code Exchange) code verifier and code challenge.\n */\nexport const generatePKCE = async (): Promise<{\n codeVerifier: string;\n codeChallenge: string;\n}> => {\n const codeVerifier = randomBytes(32);\n return {\n codeVerifier,\n codeChallenge: encodeBase64Url(\n await crypto.subtle.digest(\n 'SHA-256',\n stringToArrayBuffer(codeVerifier) as BufferSource\n )\n ),\n };\n};\n\n/**\n * Generates a random nonce string.\n */\nexport const generateNonce = (): string => randomBytes(32);\n\n/**\n * @ignore\n * Merges multiple arrays of strings, removing duplicates.\n *\n * @param args - List of arrays to merge.\n *\n * @returns A new array containing unique strings from both input arrays, or `undefined` if both inputs are `undefined`.\n */\nexport const mergeArrays = (\n ...args: (string[] | undefined)[]\n): string[] | undefined => {\n const arrays = args.filter(x => Array.isArray(x));\n return arrays.length > 0\n ? Array.from(new Set(arrays.reduce((acc, x) => [...acc, ...x], [])))\n : undefined;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/utils/index.ts"],"sourcesContent":["import type {\n AuthState,\n CallbackParams,\n IdTokenClaims,\n MonoCloudSession,\n MonoCloudUser,\n} from '../types';\nimport {\n arrayBufferToBase64,\n arrayBufferToString,\n fromB64Url,\n now,\n randomBytes,\n sha256,\n stringToArrayBuffer,\n} from './internal';\n\nconst PBKDF2_ITERATIONS = 310_000;\nconst SALT_LENGTH = 16;\nconst GCM_IV_LENGTH = 12;\n\nconst deriveEncryptionKey = async (\n secret: string,\n salt: Uint8Array\n): Promise<CryptoKey> => {\n const baseKey = await crypto.subtle.importKey(\n 'raw',\n stringToArrayBuffer(secret) as BufferSource,\n 'PBKDF2',\n false,\n ['deriveKey']\n );\n\n return crypto.subtle.deriveKey(\n {\n name: 'PBKDF2',\n salt: salt as BufferSource,\n iterations: PBKDF2_ITERATIONS,\n hash: 'SHA-256',\n },\n baseKey,\n { name: 'AES-GCM', length: 256 },\n false,\n ['encrypt', 'decrypt']\n );\n};\n\n/**\n * Parses callback parameters from a URL, a URLSearchParams object, or a query string.\n */\nexport const parseCallbackParams = (\n queryOrUrl: string | URL | URLSearchParams\n): CallbackParams => {\n let params;\n\n if (queryOrUrl instanceof URL) {\n params = queryOrUrl.searchParams;\n } else if (queryOrUrl instanceof URLSearchParams) {\n params = queryOrUrl;\n } else {\n try {\n params = new URL(queryOrUrl).searchParams;\n } catch {\n // eslint-disable-next-line no-param-reassign\n queryOrUrl =\n queryOrUrl.startsWith('?') || queryOrUrl.startsWith('#')\n ? queryOrUrl.substring(1)\n : queryOrUrl;\n params = new URLSearchParams(queryOrUrl);\n }\n }\n\n const expiresIn = params.get('expires_in');\n\n return {\n state: params.get('state') ?? undefined,\n accessToken: params.get('access_token') ?? undefined,\n idToken: params.get('id_token') ?? undefined,\n refreshToken: params.get('refresh_token') ?? undefined,\n sessionState: params.get('session_state') ?? undefined,\n expiresIn: expiresIn ? parseInt(expiresIn, 10) : undefined,\n code: params.get('code') ?? undefined,\n error: params.get('error') ?? undefined,\n errorDescription: params.get('error_description') ?? undefined,\n };\n};\n\n/**\n * Encrypts a given string using a secret with AES-GCM.\n *\n * @param data - The plaintext data to encrypt.\n * @param secret - The secret used to derive the encryption key.\n * @returns Base64-encoded ciphertext.\n */\nexport const encrypt = async (\n data: string,\n secret: string\n): Promise<string> => {\n const salt = crypto.getRandomValues(new Uint8Array(SALT_LENGTH));\n const iv = crypto.getRandomValues(new Uint8Array(GCM_IV_LENGTH));\n const plaintextBuffer = stringToArrayBuffer(data);\n const key = await deriveEncryptionKey(secret, salt);\n\n const ciphertext = await crypto.subtle.encrypt(\n {\n name: 'AES-GCM',\n iv,\n },\n key,\n plaintextBuffer as BufferSource\n );\n\n const resultBuffer = new Uint8Array(\n salt.byteLength + iv.byteLength + ciphertext.byteLength\n );\n resultBuffer.set(salt, 0);\n resultBuffer.set(iv, salt.byteLength);\n resultBuffer.set(new Uint8Array(ciphertext), salt.byteLength + iv.byteLength);\n\n return arrayBufferToBase64(resultBuffer);\n};\n\n/**\n * Decrypts an encrypted string using a secret with AES-GCM.\n *\n * @param encrypted - The ciphertext to decrypt.\n * @param secret - The secret used to derive the decryption key.\n *\n * @returns Decrypted plaintext string or undefined if decryption fails.\n */\nexport const decrypt = async (\n encrypted: string,\n secret: string\n): Promise<string | undefined> => {\n try {\n const ciphertextBuffer = Uint8Array.from(atob(fromB64Url(encrypted)), c =>\n c.charCodeAt(0)\n );\n\n if (ciphertextBuffer.byteLength <= SALT_LENGTH + GCM_IV_LENGTH) {\n return undefined;\n }\n\n const salt = ciphertextBuffer.slice(0, SALT_LENGTH);\n const iv = ciphertextBuffer.slice(SALT_LENGTH, SALT_LENGTH + GCM_IV_LENGTH);\n const encryptedPayload = ciphertextBuffer.slice(\n SALT_LENGTH + GCM_IV_LENGTH\n );\n const key = await deriveEncryptionKey(secret, salt);\n const decryptedBuffer = await crypto.subtle.decrypt(\n {\n name: 'AES-GCM',\n iv,\n },\n key,\n encryptedPayload\n );\n return arrayBufferToString(decryptedBuffer);\n } catch {\n return undefined;\n }\n};\n\n/**\n * Encrypts a MonoCloud session object with a secret and optional time-to-live (TTL).\n *\n * @param session - The session object to encrypt.\n * @param secret - The secret used for encryption.\n * @param ttl - Optional time-to-live in seconds, after which the session expires.\n * @returns Encrypted session string.\n */\nexport const encryptSession = (\n session: MonoCloudSession,\n secret: string,\n ttl?: number\n): Promise<string> => {\n let expiresAt;\n\n if (typeof ttl === 'number') {\n expiresAt = now() + ttl;\n }\n return encrypt(JSON.stringify({ session, expiresAt }), secret);\n};\n\n/**\n * Decrypts an encrypted MonoCloud session.\n *\n * @param encryptedSession - The encrypted session string to decrypt.\n * @param secret - The secret used for decryption.\n *\n * @returns Session object on success.\n *\n * @throws If decryption fails or the session has expired.\n */\nexport const decryptSession = async (\n encryptedSession: string,\n secret: string\n): Promise<MonoCloudSession> => {\n const decryptedText = await decrypt(encryptedSession, secret);\n\n if (!decryptedText) {\n throw new Error('Invalid session data');\n }\n\n let payload: { session: MonoCloudSession; expiresAt?: number };\n try {\n payload = JSON.parse(decryptedText);\n } catch {\n throw new Error('Invalid session data');\n }\n\n const { session, expiresAt } = payload;\n\n if (!session) {\n throw new Error('Invalid session data');\n }\n\n if (typeof expiresAt === 'number' && expiresAt < now()) {\n throw new Error('Session Expired');\n }\n\n return session;\n};\n\n/**\n * Encrypts an AuthState object with a secret and optional time-to-live (TTL).\n *\n * @param authState - A type that extends the AuthState interface.\n * @param secret - The secret used for encryption.\n * @param ttl - Optional time-to-live in seconds, after which the auth state expires.\n *\n * @returns Encrypted auth state string.\n */\nexport const encryptAuthState = <T extends AuthState>(\n authState: T,\n secret: string,\n ttl?: number\n): Promise<string> => {\n let expiresAt;\n\n if (typeof ttl === 'number') {\n expiresAt = now() + ttl;\n }\n\n return encrypt(JSON.stringify({ authState, expiresAt }), secret);\n};\n\n/**\n * Decrypts an encrypted AuthState.\n *\n * @param encryptedAuthState - The encrypted auth state string to decrypt.\n * @param secret - The secret used for decryption.\n *\n * @returns State object on success.\n *\n * @throws If decryption fails or the auth state has expired.\n *\n */\nexport const decryptAuthState = async <T extends AuthState>(\n encryptedAuthState: string,\n secret: string\n): Promise<T> => {\n const decryptedText = await decrypt(encryptedAuthState, secret);\n\n if (!decryptedText) {\n throw new Error('Invalid auth state');\n }\n\n let payload: { authState: T; expiresAt?: number };\n try {\n payload = JSON.parse(decryptedText);\n } catch {\n throw new Error('Invalid auth state');\n }\n\n const { authState, expiresAt } = payload;\n\n if (!authState) {\n throw new Error('Invalid auth state');\n }\n\n if (typeof expiresAt === 'number' && expiresAt < now()) {\n throw new Error('Auth state expired');\n }\n\n return authState;\n};\n\n/**\n * Checks if a user is a member of a specified group or groups.\n *\n * @param user - The user.\n * @param groups - An array of group names or IDs to check membership against.\n * @param groupsClaim - The claim in the user object that contains groups.\n * @param matchAll - If `true`, requires the user to be in all specified groups; if `false`, checks if the user is in at least one of the groups.\n *\n * @returns `true` if the user is in the specified groups, `false` otherwise.\n */\nexport const isUserInGroup = (\n user: MonoCloudUser | IdTokenClaims,\n groups: string[],\n groupsClaim = 'groups',\n matchAll = false\n): boolean => {\n const userGroups = (user[groupsClaim] ?? []) as (\n | string\n | { id: string; name: string }\n )[];\n\n if (!Array.isArray(groups) || groups.length === 0) {\n return true;\n }\n\n if (!Array.isArray(userGroups) || userGroups.length === 0) {\n return false;\n }\n\n let matched = false;\n\n for (const expectedGroup of groups) {\n const userInGroup = userGroups.some(\n g =>\n (typeof g === 'string' && g === expectedGroup) ||\n (typeof g === 'object' &&\n (g.id === expectedGroup || g.name === expectedGroup))\n );\n\n if (!matchAll && userInGroup) {\n return userInGroup;\n }\n\n if (matchAll && !userInGroup) {\n return false;\n }\n\n matched = userInGroup;\n }\n\n return matched;\n};\n\n/**\n * Generates a random state string.\n */\nexport const generateState = (): string => randomBytes(32);\n\n/**\n * Generates a PKCE (Proof Key for Code Exchange) code verifier and code challenge.\n */\nexport const generatePKCE = async (): Promise<{\n codeVerifier: string;\n codeChallenge: string;\n}> => {\n const codeVerifier = randomBytes(32);\n return {\n codeVerifier,\n codeChallenge: await sha256(codeVerifier),\n };\n};\n\n/**\n * Generates a random nonce string.\n */\nexport const generateNonce = (): string => randomBytes(32);\n\n/**\n * @ignore\n * Merges multiple arrays of strings, removing duplicates.\n *\n * @param args - List of arrays to merge.\n *\n * @returns A new array containing unique strings from both input arrays, or `undefined` if both inputs are `undefined`.\n */\nexport const mergeArrays = (\n ...args: (string[] | undefined)[]\n): string[] | undefined => {\n const arrays = args.filter(x => Array.isArray(x));\n return arrays.length > 0\n ? Array.from(new Set(arrays.reduce((acc, x) => [...acc, ...x], [])))\n : undefined;\n};\n"],"mappings":"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"}
|
package/dist/utils/internal.cjs
CHANGED
|
@@ -269,6 +269,15 @@ const encodeBase64Url = (input) => {
|
|
|
269
269
|
};
|
|
270
270
|
/**
|
|
271
271
|
* @ignore
|
|
272
|
+
* Computes a SHA-256 hash of the input string and returns it as a Base64URL encoded string.
|
|
273
|
+
*
|
|
274
|
+
* @param input - The string to hash.
|
|
275
|
+
*
|
|
276
|
+
* @returns The Base64URL encoded SHA-256 hash.
|
|
277
|
+
*/
|
|
278
|
+
const sha256 = async (input) => encodeBase64Url(await crypto.subtle.digest("SHA-256", stringToArrayBuffer(input)));
|
|
279
|
+
/**
|
|
280
|
+
* @ignore
|
|
272
281
|
* Generates a random Base64URL encoded string.
|
|
273
282
|
*
|
|
274
283
|
* @param length - The number of random bytes to generate.
|
|
@@ -387,6 +396,7 @@ exports.profileSync = profileSync;
|
|
|
387
396
|
exports.randomBytes = randomBytes;
|
|
388
397
|
exports.removeTrailingSlash = removeTrailingSlash;
|
|
389
398
|
exports.setsEqual = setsEqual;
|
|
399
|
+
exports.sha256 = sha256;
|
|
390
400
|
exports.stringToArrayBuffer = stringToArrayBuffer;
|
|
391
401
|
exports.toB64Url = toB64Url;
|
|
392
402
|
//# sourceMappingURL=internal.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.cjs","names":[],"sources":["../../src/utils/internal.ts"],"sourcesContent":["import type {\n AccessToken,\n IdTokenClaims,\n Jwk,\n MonoCloudUser,\n SecurityAlgorithms,\n JwsHeaderParameters,\n} from '../types';\n\n/**\n * @ignore\n * Converts a string to a Base64URL encoded string.\n *\n * @param input - The string to encode.\n *\n * @returns The Base64URL encoded string.\n */\nexport const toB64Url = (input: string): string =>\n input.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n\n/**\n * @ignore\n * Parses a string value into a boolean.\n *\n * @param value - The string value to parse.\n *\n * @returns `true` if \"true\", `false` if \"false\", otherwise `undefined`.\n */\nexport const getBoolean = (value?: string): boolean | undefined => {\n const v = value?.toLowerCase()?.trim();\n\n if (v === 'true') {\n return true;\n }\n\n if (v === 'false') {\n return false;\n }\n\n return undefined;\n};\n\n/**\n * @ignore\n * Parses a string value into a number.\n *\n * @param value - The string value to parse.\n *\n * @returns The parsed number, or `undefined` if empty or invalid.\n */\nexport const getNumber = (value?: string): number | undefined => {\n const v = value?.trim();\n\n if (v === undefined || v.length === 0) {\n return undefined;\n }\n\n const p = parseInt(v, 10);\n\n return Number.isNaN(p) ? undefined : p;\n};\n\n/**\n * @ignore\n * Ensures that a string has a leading forward slash.\n *\n * @param val - The string to check.\n *\n * @returns The string with a leading slash.\n */\nexport const ensureLeadingSlash = (val?: string): string => {\n const v = val?.trim();\n\n if (!v) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return v!;\n }\n\n return v.startsWith('/') ? v : `/${v}`;\n};\n\n/**\n * @ignore\n * Removes a trailing forward slash from a string.\n *\n * @param val - The string to check.\n *\n * @returns The string without a trailing slash.\n */\nexport const removeTrailingSlash = (val?: string): string => {\n const v = val?.trim();\n\n if (!v) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return v!;\n }\n\n return v.endsWith('/') ? v.substring(0, v.length - 1) : v;\n};\n\n/**\n * @ignore\n * Checks if a value is present (not null, undefined, or an empty string).\n *\n * @param value - The value to check.\n *\n * @returns `true` if the value is present, `false` otherwise.\n */\nexport const isPresent = (value?: string | number | boolean): boolean => {\n if (typeof value === 'boolean' || typeof value === 'number') {\n return true;\n }\n const v = value?.trim();\n return v !== undefined && v !== null && v.length > 0;\n};\n\n/**\n * @ignore\n * Checks if a URL is an absolute URL (starts with http:// or https://).\n *\n * @param url - The URL to check.\n *\n * @returns `true` if absolute, `false` otherwise.\n */\nexport const isAbsoluteUrl = (url: string): boolean =>\n (url?.startsWith('http://') || url?.startsWith('https://')) ?? false;\n\n/**\n * @ignore\n * Checks if two URLs have the same origin (host and port).\n *\n * @param url - The first URL.\n * @param urlToCheck - The second URL to compare against.\n *\n * @returns `true` if they share the same origin, `false` otherwise.\n */\nexport const isSameHost = (url: string, urlToCheck: string): boolean => {\n try {\n const u = new URL(url);\n const u2 = new URL(urlToCheck);\n\n return u.origin === u2.origin;\n } catch {\n return false;\n }\n};\n\n/**\n * @ignore\n * Converts a string to a Uint8Array using TextEncoder.\n *\n * @param str - The string to convert.\n *\n * @returns A Uint8Array representation of the string.\n */\nexport const stringToArrayBuffer = (str: string): Uint8Array => {\n const encoder = new TextEncoder();\n return encoder.encode(str);\n};\n\n/**\n * @ignore\n * Converts an ArrayBuffer to a string using TextDecoder.\n *\n * @param buffer - The buffer to convert.\n *\n * @returns The decoded string.\n */\nexport const arrayBufferToString = (buffer: ArrayBuffer): string => {\n const decoder = new TextDecoder();\n return decoder.decode(buffer);\n};\n\n/**\n * @ignore\n * Converts a Base64URL string back to a standard Base64 string with padding.\n *\n * @param input - The Base64URL string.\n *\n * @returns A standard Base64 string.\n */\nexport const fromB64Url = (input: string): string => {\n let str = input;\n if (str.length % 4 !== 0) {\n str += '==='.slice(0, 4 - (str.length % 4));\n }\n\n str = str.replace(/-/g, '+').replace(/_/g, '/');\n\n return str;\n};\n\n/**\n * @ignore\n * Decodes a Base64URL encoded string.\n *\n * @param input - The Base64URL string to decode.\n *\n * @returns The decoded plaintext string.\n */\nexport const decodeBase64Url = (input: string): string =>\n atob(fromB64Url(input).replace(/\\s/g, ''));\n\n/**\n * @ignore\n * Converts a Uint8Array to a Base64URL encoded string.\n *\n * @param buffer - The buffer to encode.\n *\n * @returns The Base64URL encoded string.\n */\nexport const arrayBufferToBase64 = (buffer: Uint8Array): string => {\n const bytes = new Uint8Array(buffer);\n const binary = bytes.reduce(\n (acc, byte) => acc + String.fromCharCode(byte),\n ''\n );\n return btoa(binary).replace(/=/g, '').replace(/\\+/g, '-').replace(/\\//g, '_');\n};\n\n/**\n * @ignore\n * Gets the current Unix timestamp in seconds.\n *\n * @returns The current timestamp.\n */\nexport const now = (): number => Math.ceil(Date.now() / 1000);\n\nconst SUPPORTED_JWS_ALGS: SecurityAlgorithms[] = [\n 'RS256',\n 'RS384',\n 'RS512',\n 'PS256',\n 'PS384',\n 'PS512',\n 'ES256',\n 'ES384',\n 'ES512',\n];\n\n/**\n * Retrieves a public CryptoKey from a JWK set based on the JWS header.\n *\n * @param jwks - The set of JSON Web Keys.\n * @param header - The JWS header containing the algorithm and key ID.\n *\n * @returns A promise that resolves to the CryptoKey.\n *\n * @throws If no applicable key or multiple keys are found or the algorithm is unsupported.\n */\nexport const getPublicSigKeyFromIssuerJwks = async (\n jwks: Jwk[],\n header: JwsHeaderParameters\n): Promise<CryptoKey> => {\n const { alg, kid } = header;\n\n if (!SUPPORTED_JWS_ALGS.includes(alg)) {\n throw new Error('unsupported JWS \"alg\" identifier');\n }\n\n let kty: string;\n switch (alg.slice(0, 2)) {\n case 'RS': // Fall through\n case 'PS':\n kty = 'RSA';\n break;\n case 'ES':\n kty = 'EC';\n break;\n }\n\n const candidates = jwks.filter(jwk => {\n // filter keys based on the mapping of signature algorithms to Key Type\n if (jwk.kty !== kty) {\n return false;\n }\n\n // filter keys based on the JWK Key ID in the header\n if (kid !== undefined && kid !== jwk.kid) {\n return false;\n }\n\n // filter keys based on the key's declared Algorithm\n if (jwk.alg !== undefined && alg !== jwk.alg) {\n return false;\n }\n\n // filter keys based on the key's declared Public Key Use\n if (jwk.use !== undefined && jwk.use !== 'sig') {\n return false;\n }\n\n // filter keys based on the key's declared Key Operations\n if (jwk.key_ops?.includes('verify') === false) {\n return false;\n }\n\n // filter keys based on alg-specific key requirements\n switch (true) {\n case alg === 'ES256' && jwk.crv !== 'P-256': // Fall through\n case alg === 'ES384' && jwk.crv !== 'P-384': // Fall through\n case alg === 'ES512' && jwk.crv !== 'P-521': // Fall through\n return false;\n }\n\n return true;\n });\n\n const { 0: jwk, length } = candidates;\n\n if (length !== 1) {\n throw new Error(\n 'error when selecting a JWT verification key, multiple applicable keys found, a \"kid\" JWT Header Parameter is required'\n );\n }\n\n let algorithm:\n | RsaHashedImportParams\n | EcKeyImportParams\n | AlgorithmIdentifier;\n\n switch (alg) {\n case 'PS256': // Fall through\n case 'PS384': // Fall through\n case 'PS512':\n algorithm = { name: 'RSA-PSS', hash: `SHA-${alg.slice(-3)}` };\n break;\n case 'RS256': // Fall through\n case 'RS384': // Fall through\n case 'RS512':\n algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${alg.slice(-3)}` };\n break;\n case 'ES256': // Fall through\n case 'ES384':\n algorithm = { name: 'ECDSA', namedCurve: `P-${alg.slice(-3)}` };\n break;\n case 'ES512':\n algorithm = { name: 'ECDSA', namedCurve: 'P-521' };\n break;\n }\n\n const { ext, key_ops, use, ...k } = jwk;\n\n const key = await crypto.subtle.importKey('jwk', k, algorithm, true, [\n 'verify',\n ]);\n\n if (key.type !== 'public') {\n throw new Error('jwks_uri must only contain public keys');\n }\n\n return key;\n};\n\nconst CHUNK_SIZE = 0x8000;\n\n/**\n * @ignore\n * Encodes a Uint8Array or ArrayBuffer into a Base64URL string using chunked processing.\n *\n * @param input - The data to encode.\n *\n * @returns The Base64URL encoded string.\n */\nexport const encodeBase64Url = (input: Uint8Array | ArrayBuffer): string => {\n if (input instanceof ArrayBuffer) {\n // eslint-disable-next-line no-param-reassign\n input = new Uint8Array(input);\n }\n\n const arr = [];\n for (let i = 0; i < input.byteLength; i += CHUNK_SIZE) {\n arr.push(\n String.fromCharCode.apply(\n null,\n Array.from(new Uint8Array(input.slice(i, i + CHUNK_SIZE)))\n )\n );\n }\n return btoa(arr.join(''))\n .replace(/=/g, '')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_');\n};\n\n/**\n * @ignore\n * Generates a random Base64URL encoded string.\n *\n * @param length - The number of random bytes to generate.\n *\n * @returns A random Base64URL string.\n */\nexport const randomBytes = (length = 32): string =>\n encodeBase64Url(crypto.getRandomValues(new Uint8Array(length)));\n\n/**\n * @ignore\n * Checks if a value is a non-null, non-array JSON object.\n *\n * @param input - The value to check.\n *\n * @returns `true` if the value is a JSON object.\n */\nexport const isJsonObject = <T>(input: unknown): input is T => {\n if (input === null || typeof input !== 'object' || Array.isArray(input)) {\n return false;\n }\n\n return true;\n};\n\n/**\n * @ignore\n * Parses a space-separated string into an array of strings.\n *\n * @param s - The space-separated string.\n *\n * @returns An array of strings, or `undefined` if input is empty.\n */\nexport const parseSpaceSeparated = (s?: string): string[] | undefined =>\n s\n ?.split(/\\s+/)\n .map(x => x.trim())\n .filter(Boolean);\n\n/**\n * @ignore\n * Parses a space-separated string into a Set of strings.\n *\n * @param s - The space-separated string.\n *\n * @returns A Set containing the unique strings.\n */\nexport const parseSpaceSeparatedSet = (s?: string): Set<string> => {\n if (!s) {\n return new Set();\n }\n\n return new Set(parseSpaceSeparated(s));\n};\n\n/**\n * @ignore\n * Compares two Sets for equality.\n *\n * @param a - The first Set.\n * @param b - The second Set.\n * @param strict - If `true`, requires both sets to be the same size. Defaults to `true`.\n *\n * @returns `true` if the sets are equal.\n */\nexport const setsEqual = (\n a: Set<string>,\n b: Set<string>,\n strict = true\n): boolean => {\n if (strict && a.size !== b.size) {\n return false;\n }\n\n for (const v of a) {\n if (!b.has(v)) {\n return false;\n }\n }\n\n return true;\n};\n\n/**\n * Finds a specific access token in an array based on resource and scopes.\n *\n * @param tokens - The array of access tokens.\n * @param resource - Space-separated resource indicators.\n * @param scopes - Space-separated scopes.\n *\n * @returns The matching AccessToken, or `undefined` if not found.\n */\nexport const findToken = (\n tokens?: AccessToken[],\n resource?: string,\n scopes?: string\n): AccessToken | undefined => {\n if (!Array.isArray(tokens) || tokens.length === 0) {\n return undefined;\n }\n\n const desiredResource = parseSpaceSeparatedSet(resource);\n const desiredScopes = parseSpaceSeparatedSet(scopes);\n\n return tokens.find(\n t =>\n setsEqual(desiredResource, parseSpaceSeparatedSet(t.resource)) &&\n setsEqual(desiredScopes, parseSpaceSeparatedSet(t.requestedScopes))\n );\n};\n\n/**\n * @ignore\n * Builds the session user claims from existing claims and newly fetched claims.\n *\n * @param existingUser - Existing session user claims.\n * @param idTokenClaims - Claims extracted from ID token.\n * @param userinfoClaims - Claims fetched from UserInfo endpoint.\n * @param strict - If `true`, creates claims from new inputs only (falls back to existing when none). If `false`, merges into existing claims.\n *\n * @returns Updated user claims for the session.\n */\nexport const profileSync = (\n existingUser?: MonoCloudUser,\n idTokenClaims?: Partial<IdTokenClaims>,\n userinfoClaims?: Partial<MonoCloudUser>,\n strict = false\n): MonoCloudUser => {\n const hasIdTokenClaims =\n !!idTokenClaims && Object.keys(idTokenClaims).length > 0;\n const hasUserinfoClaims =\n !!userinfoClaims && Object.keys(userinfoClaims).length > 0;\n\n if (!hasIdTokenClaims && !hasUserinfoClaims) {\n return existingUser ?? ({} as MonoCloudUser);\n }\n\n if (strict) {\n return {\n ...(idTokenClaims ?? {}),\n ...(userinfoClaims ?? {}),\n } as MonoCloudUser;\n }\n\n return {\n ...(existingUser ?? {}),\n ...(idTokenClaims ?? {}),\n ...(userinfoClaims ?? {}),\n } as MonoCloudUser;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"internal.cjs","names":[],"sources":["../../src/utils/internal.ts"],"sourcesContent":["import type {\n AccessToken,\n IdTokenClaims,\n Jwk,\n MonoCloudUser,\n SecurityAlgorithms,\n JwsHeaderParameters,\n} from '../types';\n\n/**\n * @ignore\n * Converts a string to a Base64URL encoded string.\n *\n * @param input - The string to encode.\n *\n * @returns The Base64URL encoded string.\n */\nexport const toB64Url = (input: string): string =>\n input.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n\n/**\n * @ignore\n * Parses a string value into a boolean.\n *\n * @param value - The string value to parse.\n *\n * @returns `true` if \"true\", `false` if \"false\", otherwise `undefined`.\n */\nexport const getBoolean = (value?: string): boolean | undefined => {\n const v = value?.toLowerCase()?.trim();\n\n if (v === 'true') {\n return true;\n }\n\n if (v === 'false') {\n return false;\n }\n\n return undefined;\n};\n\n/**\n * @ignore\n * Parses a string value into a number.\n *\n * @param value - The string value to parse.\n *\n * @returns The parsed number, or `undefined` if empty or invalid.\n */\nexport const getNumber = (value?: string): number | undefined => {\n const v = value?.trim();\n\n if (v === undefined || v.length === 0) {\n return undefined;\n }\n\n const p = parseInt(v, 10);\n\n return Number.isNaN(p) ? undefined : p;\n};\n\n/**\n * @ignore\n * Ensures that a string has a leading forward slash.\n *\n * @param val - The string to check.\n *\n * @returns The string with a leading slash.\n */\nexport const ensureLeadingSlash = (val?: string): string => {\n const v = val?.trim();\n\n if (!v) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return v!;\n }\n\n return v.startsWith('/') ? v : `/${v}`;\n};\n\n/**\n * @ignore\n * Removes a trailing forward slash from a string.\n *\n * @param val - The string to check.\n *\n * @returns The string without a trailing slash.\n */\nexport const removeTrailingSlash = (val?: string): string => {\n const v = val?.trim();\n\n if (!v) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return v!;\n }\n\n return v.endsWith('/') ? v.substring(0, v.length - 1) : v;\n};\n\n/**\n * @ignore\n * Checks if a value is present (not null, undefined, or an empty string).\n *\n * @param value - The value to check.\n *\n * @returns `true` if the value is present, `false` otherwise.\n */\nexport const isPresent = (value?: string | number | boolean): boolean => {\n if (typeof value === 'boolean' || typeof value === 'number') {\n return true;\n }\n const v = value?.trim();\n return v !== undefined && v !== null && v.length > 0;\n};\n\n/**\n * @ignore\n * Checks if a URL is an absolute URL (starts with http:// or https://).\n *\n * @param url - The URL to check.\n *\n * @returns `true` if absolute, `false` otherwise.\n */\nexport const isAbsoluteUrl = (url: string): boolean =>\n (url?.startsWith('http://') || url?.startsWith('https://')) ?? false;\n\n/**\n * @ignore\n * Checks if two URLs have the same origin (host and port).\n *\n * @param url - The first URL.\n * @param urlToCheck - The second URL to compare against.\n *\n * @returns `true` if they share the same origin, `false` otherwise.\n */\nexport const isSameHost = (url: string, urlToCheck: string): boolean => {\n try {\n const u = new URL(url);\n const u2 = new URL(urlToCheck);\n\n return u.origin === u2.origin;\n } catch {\n return false;\n }\n};\n\n/**\n * @ignore\n * Converts a string to a Uint8Array using TextEncoder.\n *\n * @param str - The string to convert.\n *\n * @returns A Uint8Array representation of the string.\n */\nexport const stringToArrayBuffer = (str: string): Uint8Array => {\n const encoder = new TextEncoder();\n return encoder.encode(str);\n};\n\n/**\n * @ignore\n * Converts an ArrayBuffer to a string using TextDecoder.\n *\n * @param buffer - The buffer to convert.\n *\n * @returns The decoded string.\n */\nexport const arrayBufferToString = (buffer: ArrayBuffer): string => {\n const decoder = new TextDecoder();\n return decoder.decode(buffer);\n};\n\n/**\n * @ignore\n * Converts a Base64URL string back to a standard Base64 string with padding.\n *\n * @param input - The Base64URL string.\n *\n * @returns A standard Base64 string.\n */\nexport const fromB64Url = (input: string): string => {\n let str = input;\n if (str.length % 4 !== 0) {\n str += '==='.slice(0, 4 - (str.length % 4));\n }\n\n str = str.replace(/-/g, '+').replace(/_/g, '/');\n\n return str;\n};\n\n/**\n * @ignore\n * Decodes a Base64URL encoded string.\n *\n * @param input - The Base64URL string to decode.\n *\n * @returns The decoded plaintext string.\n */\nexport const decodeBase64Url = (input: string): string =>\n atob(fromB64Url(input).replace(/\\s/g, ''));\n\n/**\n * @ignore\n * Converts a Uint8Array to a Base64URL encoded string.\n *\n * @param buffer - The buffer to encode.\n *\n * @returns The Base64URL encoded string.\n */\nexport const arrayBufferToBase64 = (buffer: Uint8Array): string => {\n const bytes = new Uint8Array(buffer);\n const binary = bytes.reduce(\n (acc, byte) => acc + String.fromCharCode(byte),\n ''\n );\n return btoa(binary).replace(/=/g, '').replace(/\\+/g, '-').replace(/\\//g, '_');\n};\n\n/**\n * @ignore\n * Gets the current Unix timestamp in seconds.\n *\n * @returns The current timestamp.\n */\nexport const now = (): number => Math.ceil(Date.now() / 1000);\n\nconst SUPPORTED_JWS_ALGS: SecurityAlgorithms[] = [\n 'RS256',\n 'RS384',\n 'RS512',\n 'PS256',\n 'PS384',\n 'PS512',\n 'ES256',\n 'ES384',\n 'ES512',\n];\n\n/**\n * Retrieves a public CryptoKey from a JWK set based on the JWS header.\n *\n * @param jwks - The set of JSON Web Keys.\n * @param header - The JWS header containing the algorithm and key ID.\n *\n * @returns A promise that resolves to the CryptoKey.\n *\n * @throws If no applicable key or multiple keys are found or the algorithm is unsupported.\n */\nexport const getPublicSigKeyFromIssuerJwks = async (\n jwks: Jwk[],\n header: JwsHeaderParameters\n): Promise<CryptoKey> => {\n const { alg, kid } = header;\n\n if (!SUPPORTED_JWS_ALGS.includes(alg)) {\n throw new Error('unsupported JWS \"alg\" identifier');\n }\n\n let kty: string;\n switch (alg.slice(0, 2)) {\n case 'RS': // Fall through\n case 'PS':\n kty = 'RSA';\n break;\n case 'ES':\n kty = 'EC';\n break;\n }\n\n const candidates = jwks.filter(jwk => {\n // filter keys based on the mapping of signature algorithms to Key Type\n if (jwk.kty !== kty) {\n return false;\n }\n\n // filter keys based on the JWK Key ID in the header\n if (kid !== undefined && kid !== jwk.kid) {\n return false;\n }\n\n // filter keys based on the key's declared Algorithm\n if (jwk.alg !== undefined && alg !== jwk.alg) {\n return false;\n }\n\n // filter keys based on the key's declared Public Key Use\n if (jwk.use !== undefined && jwk.use !== 'sig') {\n return false;\n }\n\n // filter keys based on the key's declared Key Operations\n if (jwk.key_ops?.includes('verify') === false) {\n return false;\n }\n\n // filter keys based on alg-specific key requirements\n switch (true) {\n case alg === 'ES256' && jwk.crv !== 'P-256': // Fall through\n case alg === 'ES384' && jwk.crv !== 'P-384': // Fall through\n case alg === 'ES512' && jwk.crv !== 'P-521': // Fall through\n return false;\n }\n\n return true;\n });\n\n const { 0: jwk, length } = candidates;\n\n if (length !== 1) {\n throw new Error(\n 'error when selecting a JWT verification key, multiple applicable keys found, a \"kid\" JWT Header Parameter is required'\n );\n }\n\n let algorithm:\n | RsaHashedImportParams\n | EcKeyImportParams\n | AlgorithmIdentifier;\n\n switch (alg) {\n case 'PS256': // Fall through\n case 'PS384': // Fall through\n case 'PS512':\n algorithm = { name: 'RSA-PSS', hash: `SHA-${alg.slice(-3)}` };\n break;\n case 'RS256': // Fall through\n case 'RS384': // Fall through\n case 'RS512':\n algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${alg.slice(-3)}` };\n break;\n case 'ES256': // Fall through\n case 'ES384':\n algorithm = { name: 'ECDSA', namedCurve: `P-${alg.slice(-3)}` };\n break;\n case 'ES512':\n algorithm = { name: 'ECDSA', namedCurve: 'P-521' };\n break;\n }\n\n const { ext, key_ops, use, ...k } = jwk;\n\n const key = await crypto.subtle.importKey('jwk', k, algorithm, true, [\n 'verify',\n ]);\n\n if (key.type !== 'public') {\n throw new Error('jwks_uri must only contain public keys');\n }\n\n return key;\n};\n\nconst CHUNK_SIZE = 0x8000;\n\n/**\n * @ignore\n * Encodes a Uint8Array or ArrayBuffer into a Base64URL string using chunked processing.\n *\n * @param input - The data to encode.\n *\n * @returns The Base64URL encoded string.\n */\nexport const encodeBase64Url = (input: Uint8Array | ArrayBuffer): string => {\n if (input instanceof ArrayBuffer) {\n // eslint-disable-next-line no-param-reassign\n input = new Uint8Array(input);\n }\n\n const arr = [];\n for (let i = 0; i < input.byteLength; i += CHUNK_SIZE) {\n arr.push(\n String.fromCharCode.apply(\n null,\n Array.from(new Uint8Array(input.slice(i, i + CHUNK_SIZE)))\n )\n );\n }\n return btoa(arr.join(''))\n .replace(/=/g, '')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_');\n};\n\n/**\n * @ignore\n * Computes a SHA-256 hash of the input string and returns it as a Base64URL encoded string.\n *\n * @param input - The string to hash.\n *\n * @returns The Base64URL encoded SHA-256 hash.\n */\nexport const sha256 = async (input: string): Promise<string> =>\n encodeBase64Url(\n await crypto.subtle.digest(\n 'SHA-256',\n stringToArrayBuffer(input) as BufferSource\n )\n );\n\n/**\n * @ignore\n * Generates a random Base64URL encoded string.\n *\n * @param length - The number of random bytes to generate.\n *\n * @returns A random Base64URL string.\n */\nexport const randomBytes = (length = 32): string =>\n encodeBase64Url(crypto.getRandomValues(new Uint8Array(length)));\n\n/**\n * @ignore\n * Checks if a value is a non-null, non-array JSON object.\n *\n * @param input - The value to check.\n *\n * @returns `true` if the value is a JSON object.\n */\nexport const isJsonObject = <T>(input: unknown): input is T => {\n if (input === null || typeof input !== 'object' || Array.isArray(input)) {\n return false;\n }\n\n return true;\n};\n\n/**\n * @ignore\n * Parses a space-separated string into an array of strings.\n *\n * @param s - The space-separated string.\n *\n * @returns An array of strings, or `undefined` if input is empty.\n */\nexport const parseSpaceSeparated = (s?: string): string[] | undefined =>\n s\n ?.split(/\\s+/)\n .map(x => x.trim())\n .filter(Boolean);\n\n/**\n * @ignore\n * Parses a space-separated string into a Set of strings.\n *\n * @param s - The space-separated string.\n *\n * @returns A Set containing the unique strings.\n */\nexport const parseSpaceSeparatedSet = (s?: string): Set<string> => {\n if (!s) {\n return new Set();\n }\n\n return new Set(parseSpaceSeparated(s));\n};\n\n/**\n * @ignore\n * Compares two Sets for equality.\n *\n * @param a - The first Set.\n * @param b - The second Set.\n * @param strict - If `true`, requires both sets to be the same size. Defaults to `true`.\n *\n * @returns `true` if the sets are equal.\n */\nexport const setsEqual = (\n a: Set<string>,\n b: Set<string>,\n strict = true\n): boolean => {\n if (strict && a.size !== b.size) {\n return false;\n }\n\n for (const v of a) {\n if (!b.has(v)) {\n return false;\n }\n }\n\n return true;\n};\n\n/**\n * Finds a specific access token in an array based on resource and scopes.\n *\n * @param tokens - The array of access tokens.\n * @param resource - Space-separated resource indicators.\n * @param scopes - Space-separated scopes.\n *\n * @returns The matching AccessToken, or `undefined` if not found.\n */\nexport const findToken = (\n tokens?: AccessToken[],\n resource?: string,\n scopes?: string\n): AccessToken | undefined => {\n if (!Array.isArray(tokens) || tokens.length === 0) {\n return undefined;\n }\n\n const desiredResource = parseSpaceSeparatedSet(resource);\n const desiredScopes = parseSpaceSeparatedSet(scopes);\n\n return tokens.find(\n t =>\n setsEqual(desiredResource, parseSpaceSeparatedSet(t.resource)) &&\n setsEqual(desiredScopes, parseSpaceSeparatedSet(t.requestedScopes))\n );\n};\n\n/**\n * @ignore\n * Builds the session user claims from existing claims and newly fetched claims.\n *\n * @param existingUser - Existing session user claims.\n * @param idTokenClaims - Claims extracted from ID token.\n * @param userinfoClaims - Claims fetched from UserInfo endpoint.\n * @param strict - If `true`, creates claims from new inputs only (falls back to existing when none). If `false`, merges into existing claims.\n *\n * @returns Updated user claims for the session.\n */\nexport const profileSync = (\n existingUser?: MonoCloudUser,\n idTokenClaims?: Partial<IdTokenClaims>,\n userinfoClaims?: Partial<MonoCloudUser>,\n strict = false\n): MonoCloudUser => {\n const hasIdTokenClaims =\n !!idTokenClaims && Object.keys(idTokenClaims).length > 0;\n const hasUserinfoClaims =\n !!userinfoClaims && Object.keys(userinfoClaims).length > 0;\n\n if (!hasIdTokenClaims && !hasUserinfoClaims) {\n return existingUser ?? ({} as MonoCloudUser);\n }\n\n if (strict) {\n return {\n ...(idTokenClaims ?? {}),\n ...(userinfoClaims ?? {}),\n } as MonoCloudUser;\n }\n\n return {\n ...(existingUser ?? {}),\n ...(idTokenClaims ?? {}),\n ...(userinfoClaims ?? {}),\n } as MonoCloudUser;\n};\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { E as MonoCloudUser, b as JwsHeaderParameters, m as IdTokenClaims, t as AccessToken, v as Jwk } from "../types-BVOv1R0s.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/utils/internal.d.ts
|
|
4
4
|
/**
|
|
@@ -146,6 +146,15 @@ declare const getPublicSigKeyFromIssuerJwks: (jwks: Jwk[], header: JwsHeaderPara
|
|
|
146
146
|
* @returns The Base64URL encoded string.
|
|
147
147
|
*/
|
|
148
148
|
declare const encodeBase64Url: (input: Uint8Array | ArrayBuffer) => string;
|
|
149
|
+
/**
|
|
150
|
+
* @ignore
|
|
151
|
+
* Computes a SHA-256 hash of the input string and returns it as a Base64URL encoded string.
|
|
152
|
+
*
|
|
153
|
+
* @param input - The string to hash.
|
|
154
|
+
*
|
|
155
|
+
* @returns The Base64URL encoded SHA-256 hash.
|
|
156
|
+
*/
|
|
157
|
+
declare const sha256: (input: string) => Promise<string>;
|
|
149
158
|
/**
|
|
150
159
|
* @ignore
|
|
151
160
|
* Generates a random Base64URL encoded string.
|
|
@@ -216,5 +225,5 @@ declare const findToken: (tokens?: AccessToken[], resource?: string, scopes?: st
|
|
|
216
225
|
*/
|
|
217
226
|
declare const profileSync: (existingUser?: MonoCloudUser, idTokenClaims?: Partial<IdTokenClaims>, userinfoClaims?: Partial<MonoCloudUser>, strict?: boolean) => MonoCloudUser;
|
|
218
227
|
//#endregion
|
|
219
|
-
export { arrayBufferToBase64, arrayBufferToString, decodeBase64Url, encodeBase64Url, ensureLeadingSlash, findToken, fromB64Url, getBoolean, getNumber, getPublicSigKeyFromIssuerJwks, isAbsoluteUrl, isJsonObject, isPresent, isSameHost, now, parseSpaceSeparated, parseSpaceSeparatedSet, profileSync, randomBytes, removeTrailingSlash, setsEqual, stringToArrayBuffer, toB64Url };
|
|
228
|
+
export { arrayBufferToBase64, arrayBufferToString, decodeBase64Url, encodeBase64Url, ensureLeadingSlash, findToken, fromB64Url, getBoolean, getNumber, getPublicSigKeyFromIssuerJwks, isAbsoluteUrl, isJsonObject, isPresent, isSameHost, now, parseSpaceSeparated, parseSpaceSeparatedSet, profileSync, randomBytes, removeTrailingSlash, setsEqual, sha256, stringToArrayBuffer, toB64Url };
|
|
220
229
|
//# sourceMappingURL=internal.d.mts.map
|
package/dist/utils/internal.mjs
CHANGED
|
@@ -267,6 +267,15 @@ const encodeBase64Url = (input) => {
|
|
|
267
267
|
};
|
|
268
268
|
/**
|
|
269
269
|
* @ignore
|
|
270
|
+
* Computes a SHA-256 hash of the input string and returns it as a Base64URL encoded string.
|
|
271
|
+
*
|
|
272
|
+
* @param input - The string to hash.
|
|
273
|
+
*
|
|
274
|
+
* @returns The Base64URL encoded SHA-256 hash.
|
|
275
|
+
*/
|
|
276
|
+
const sha256 = async (input) => encodeBase64Url(await crypto.subtle.digest("SHA-256", stringToArrayBuffer(input)));
|
|
277
|
+
/**
|
|
278
|
+
* @ignore
|
|
270
279
|
* Generates a random Base64URL encoded string.
|
|
271
280
|
*
|
|
272
281
|
* @param length - The number of random bytes to generate.
|
|
@@ -364,5 +373,5 @@ const profileSync = (existingUser, idTokenClaims, userinfoClaims, strict = false
|
|
|
364
373
|
};
|
|
365
374
|
|
|
366
375
|
//#endregion
|
|
367
|
-
export { arrayBufferToBase64, arrayBufferToString, decodeBase64Url, encodeBase64Url, ensureLeadingSlash, findToken, fromB64Url, getBoolean, getNumber, getPublicSigKeyFromIssuerJwks, isAbsoluteUrl, isJsonObject, isPresent, isSameHost, now, parseSpaceSeparated, parseSpaceSeparatedSet, profileSync, randomBytes, removeTrailingSlash, setsEqual, stringToArrayBuffer, toB64Url };
|
|
376
|
+
export { arrayBufferToBase64, arrayBufferToString, decodeBase64Url, encodeBase64Url, ensureLeadingSlash, findToken, fromB64Url, getBoolean, getNumber, getPublicSigKeyFromIssuerJwks, isAbsoluteUrl, isJsonObject, isPresent, isSameHost, now, parseSpaceSeparated, parseSpaceSeparatedSet, profileSync, randomBytes, removeTrailingSlash, setsEqual, sha256, stringToArrayBuffer, toB64Url };
|
|
368
377
|
//# sourceMappingURL=internal.mjs.map
|