@monocloud/auth-core 0.1.4 → 0.1.6
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 +70 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +72 -35
- package/dist/index.mjs +70 -35
- package/dist/index.mjs.map +1 -1
- package/dist/types-Dox1pap7.d.mts +1243 -0
- package/dist/utils/index.cjs +4 -5
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.mts +5 -6
- package/dist/utils/index.mjs +4 -5
- package/dist/utils/index.mjs.map +1 -1
- package/dist/utils/internal.cjs +4 -4
- package/dist/utils/internal.cjs.map +1 -1
- package/dist/utils/internal.d.mts +5 -5
- package/dist/utils/internal.mjs +4 -4
- package/dist/utils/internal.mjs.map +1 -1
- package/package.json +3 -3
- package/dist/index.d.cts +0 -274
- package/dist/types-BAE9nCpJ.d.cts +0 -481
- package/dist/types-D3lVLgLQ.d.mts +0 -481
- package/dist/utils/index.d.cts +0 -105
- package/dist/utils/internal.d.cts +0 -208
package/dist/utils/index.cjs
CHANGED
|
@@ -113,7 +113,7 @@ const encryptSession = (session, secret, ttl) => {
|
|
|
113
113
|
*
|
|
114
114
|
* @returns Session object on success.
|
|
115
115
|
*
|
|
116
|
-
* @throws If decryption fails or the session has expired
|
|
116
|
+
* @throws If decryption fails or the session has expired.
|
|
117
117
|
*/
|
|
118
118
|
const decryptSession = async (encryptedSession, secret) => {
|
|
119
119
|
const decryptedText = await decrypt(encryptedSession, secret);
|
|
@@ -152,9 +152,9 @@ const encryptAuthState = (authState, secret, ttl) => {
|
|
|
152
152
|
* @param encryptedAuthState - The encrypted auth state string to decrypt.
|
|
153
153
|
* @param secret - The secret used for decryption.
|
|
154
154
|
*
|
|
155
|
-
* @returns State object on success
|
|
155
|
+
* @returns State object on success.
|
|
156
156
|
*
|
|
157
|
-
* @throws If decryption fails or the auth state has expired
|
|
157
|
+
* @throws If decryption fails or the auth state has expired.
|
|
158
158
|
*
|
|
159
159
|
*/
|
|
160
160
|
const decryptAuthState = async (encryptedAuthState, secret) => {
|
|
@@ -200,7 +200,6 @@ const isUserInGroup = (user, groups, groupsClaim = "groups", matchAll = false) =
|
|
|
200
200
|
const generateState = () => require_utils_internal.randomBytes(32);
|
|
201
201
|
/**
|
|
202
202
|
* Generates a PKCE (Proof Key for Code Exchange) code verifier and code challenge.
|
|
203
|
-
*
|
|
204
203
|
*/
|
|
205
204
|
const generatePKCE = async () => {
|
|
206
205
|
const codeVerifier = require_utils_internal.randomBytes(32);
|
|
@@ -217,7 +216,7 @@ const generateNonce = () => require_utils_internal.randomBytes(32);
|
|
|
217
216
|
* @ignore
|
|
218
217
|
* Merges multiple arrays of strings, removing duplicates.
|
|
219
218
|
*
|
|
220
|
-
* @param args - List of arrays to merge
|
|
219
|
+
* @param args - List of arrays to merge.
|
|
221
220
|
*
|
|
222
221
|
* @returns A new array containing unique strings from both input arrays, or `undefined` if both inputs are `undefined`.
|
|
223
222
|
*/
|
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 *\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","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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"}
|
package/dist/utils/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as
|
|
1
|
+
import { b as MonoCloudUser, p as IdTokenClaims, r as AuthState, s as CallbackParams, y as MonoCloudSession } from "../types-Dox1pap7.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/utils/index.d.ts
|
|
4
4
|
/**
|
|
@@ -39,7 +39,7 @@ declare const encryptSession: (session: MonoCloudSession, secret: string, ttl?:
|
|
|
39
39
|
*
|
|
40
40
|
* @returns Session object on success.
|
|
41
41
|
*
|
|
42
|
-
* @throws If decryption fails or the session has expired
|
|
42
|
+
* @throws If decryption fails or the session has expired.
|
|
43
43
|
*/
|
|
44
44
|
declare const decryptSession: (encryptedSession: string, secret: string) => Promise<MonoCloudSession>;
|
|
45
45
|
/**
|
|
@@ -58,9 +58,9 @@ declare const encryptAuthState: <T extends AuthState>(authState: T, secret: stri
|
|
|
58
58
|
* @param encryptedAuthState - The encrypted auth state string to decrypt.
|
|
59
59
|
* @param secret - The secret used for decryption.
|
|
60
60
|
*
|
|
61
|
-
* @returns State object on success
|
|
61
|
+
* @returns State object on success.
|
|
62
62
|
*
|
|
63
|
-
* @throws If decryption fails or the auth state has expired
|
|
63
|
+
* @throws If decryption fails or the auth state has expired.
|
|
64
64
|
*
|
|
65
65
|
*/
|
|
66
66
|
declare const decryptAuthState: <T extends AuthState>(encryptedAuthState: string, secret: string) => Promise<T>;
|
|
@@ -81,7 +81,6 @@ declare const isUserInGroup: (user: MonoCloudUser | IdTokenClaims, groups: strin
|
|
|
81
81
|
declare const generateState: () => string;
|
|
82
82
|
/**
|
|
83
83
|
* Generates a PKCE (Proof Key for Code Exchange) code verifier and code challenge.
|
|
84
|
-
*
|
|
85
84
|
*/
|
|
86
85
|
declare const generatePKCE: () => Promise<{
|
|
87
86
|
codeVerifier: string;
|
|
@@ -95,7 +94,7 @@ declare const generateNonce: () => string;
|
|
|
95
94
|
* @ignore
|
|
96
95
|
* Merges multiple arrays of strings, removing duplicates.
|
|
97
96
|
*
|
|
98
|
-
* @param args - List of arrays to merge
|
|
97
|
+
* @param args - List of arrays to merge.
|
|
99
98
|
*
|
|
100
99
|
* @returns A new array containing unique strings from both input arrays, or `undefined` if both inputs are `undefined`.
|
|
101
100
|
*/
|
package/dist/utils/index.mjs
CHANGED
|
@@ -112,7 +112,7 @@ const encryptSession = (session, secret, ttl) => {
|
|
|
112
112
|
*
|
|
113
113
|
* @returns Session object on success.
|
|
114
114
|
*
|
|
115
|
-
* @throws If decryption fails or the session has expired
|
|
115
|
+
* @throws If decryption fails or the session has expired.
|
|
116
116
|
*/
|
|
117
117
|
const decryptSession = async (encryptedSession, secret) => {
|
|
118
118
|
const decryptedText = await decrypt(encryptedSession, secret);
|
|
@@ -151,9 +151,9 @@ const encryptAuthState = (authState, secret, ttl) => {
|
|
|
151
151
|
* @param encryptedAuthState - The encrypted auth state string to decrypt.
|
|
152
152
|
* @param secret - The secret used for decryption.
|
|
153
153
|
*
|
|
154
|
-
* @returns State object on success
|
|
154
|
+
* @returns State object on success.
|
|
155
155
|
*
|
|
156
|
-
* @throws If decryption fails or the auth state has expired
|
|
156
|
+
* @throws If decryption fails or the auth state has expired.
|
|
157
157
|
*
|
|
158
158
|
*/
|
|
159
159
|
const decryptAuthState = async (encryptedAuthState, secret) => {
|
|
@@ -199,7 +199,6 @@ const isUserInGroup = (user, groups, groupsClaim = "groups", matchAll = false) =
|
|
|
199
199
|
const generateState = () => randomBytes(32);
|
|
200
200
|
/**
|
|
201
201
|
* Generates a PKCE (Proof Key for Code Exchange) code verifier and code challenge.
|
|
202
|
-
*
|
|
203
202
|
*/
|
|
204
203
|
const generatePKCE = async () => {
|
|
205
204
|
const codeVerifier = randomBytes(32);
|
|
@@ -216,7 +215,7 @@ const generateNonce = () => randomBytes(32);
|
|
|
216
215
|
* @ignore
|
|
217
216
|
* Merges multiple arrays of strings, removing duplicates.
|
|
218
217
|
*
|
|
219
|
-
* @param args - List of arrays to merge
|
|
218
|
+
* @param args - List of arrays to merge.
|
|
220
219
|
*
|
|
221
220
|
* @returns A new array containing unique strings from both input arrays, or `undefined` if both inputs are `undefined`.
|
|
222
221
|
*/
|
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 *\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 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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"}
|
package/dist/utils/internal.cjs
CHANGED
|
@@ -313,11 +313,11 @@ const parseSpaceSeparatedSet = (s) => {
|
|
|
313
313
|
* @ignore
|
|
314
314
|
* Compares two Sets for equality.
|
|
315
315
|
*
|
|
316
|
-
* @param a - The first Set
|
|
317
|
-
* @param b - The second Set
|
|
318
|
-
* @param strict - If `true`, requires both sets to be the same size.
|
|
316
|
+
* @param a - The first Set.
|
|
317
|
+
* @param b - The second Set.
|
|
318
|
+
* @param strict - If `true`, requires both sets to be the same size. Defaults to `true`.
|
|
319
319
|
*
|
|
320
|
-
* @returns `true` if the sets are equal
|
|
320
|
+
* @returns `true` if the sets are equal.
|
|
321
321
|
*/
|
|
322
322
|
const setsEqual = (a, b, strict = true) => {
|
|
323
323
|
if (strict && a.size !== b.size) return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.cjs","names":[],"sources":["../../src/utils/internal.ts"],"sourcesContent":["import type {\n AccessToken,\n Jwk,\n JWSAlgorithm,\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: JWSAlgorithm[] = [\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. @defaultValue 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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"internal.cjs","names":[],"sources":["../../src/utils/internal.ts"],"sourcesContent":["import type {\n AccessToken,\n Jwk,\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"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as JwsHeaderParameters, h as Jwk, t as AccessToken } from "../types-Dox1pap7.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/utils/internal.d.ts
|
|
4
4
|
/**
|
|
@@ -186,11 +186,11 @@ declare const parseSpaceSeparatedSet: (s?: string) => Set<string>;
|
|
|
186
186
|
* @ignore
|
|
187
187
|
* Compares two Sets for equality.
|
|
188
188
|
*
|
|
189
|
-
* @param a - The first Set
|
|
190
|
-
* @param b - The second Set
|
|
191
|
-
* @param strict - If `true`, requires both sets to be the same size.
|
|
189
|
+
* @param a - The first Set.
|
|
190
|
+
* @param b - The second Set.
|
|
191
|
+
* @param strict - If `true`, requires both sets to be the same size. Defaults to `true`.
|
|
192
192
|
*
|
|
193
|
-
* @returns `true` if the sets are equal
|
|
193
|
+
* @returns `true` if the sets are equal.
|
|
194
194
|
*/
|
|
195
195
|
declare const setsEqual: (a: Set<string>, b: Set<string>, strict?: boolean) => boolean;
|
|
196
196
|
/**
|
package/dist/utils/internal.mjs
CHANGED
|
@@ -311,11 +311,11 @@ const parseSpaceSeparatedSet = (s) => {
|
|
|
311
311
|
* @ignore
|
|
312
312
|
* Compares two Sets for equality.
|
|
313
313
|
*
|
|
314
|
-
* @param a - The first Set
|
|
315
|
-
* @param b - The second Set
|
|
316
|
-
* @param strict - If `true`, requires both sets to be the same size.
|
|
314
|
+
* @param a - The first Set.
|
|
315
|
+
* @param b - The second Set.
|
|
316
|
+
* @param strict - If `true`, requires both sets to be the same size. Defaults to `true`.
|
|
317
317
|
*
|
|
318
|
-
* @returns `true` if the sets are equal
|
|
318
|
+
* @returns `true` if the sets are equal.
|
|
319
319
|
*/
|
|
320
320
|
const setsEqual = (a, b, strict = true) => {
|
|
321
321
|
if (strict && a.size !== b.size) return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.mjs","names":[],"sources":["../../src/utils/internal.ts"],"sourcesContent":["import type {\n AccessToken,\n Jwk,\n JWSAlgorithm,\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: JWSAlgorithm[] = [\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. @defaultValue 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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"internal.mjs","names":[],"sources":["../../src/utils/internal.ts"],"sourcesContent":["import type {\n AccessToken,\n Jwk,\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"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monocloud/auth-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "MonoCloud Authentication JavaScript Core SDK",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"monocloud",
|
|
@@ -25,7 +25,6 @@
|
|
|
25
25
|
"email": "support@monocloud.com"
|
|
26
26
|
},
|
|
27
27
|
"main": "./dist/index.cjs",
|
|
28
|
-
"module": "./dist/index.mjs",
|
|
29
28
|
"types": "./dist/index.d.mts",
|
|
30
29
|
"exports": {
|
|
31
30
|
".": {
|
|
@@ -61,5 +60,6 @@
|
|
|
61
60
|
"lint": "pnpm run lint:es && pnpm run lint:ts",
|
|
62
61
|
"test": "eslint tests && rimraf coverage && vitest --config vitest.node.config.mts && vitest --config vitest.edge.config.mts && vitest --config vitest.browser.config.mts && pnpm report",
|
|
63
62
|
"report": "shx cp ./coverage/node/coverage-final.json ./coverage/coverage-0.json && shx cp ./coverage/edge/coverage-final.json ./coverage/coverage-1.json && shx cp ./coverage/browser/coverage-final.json ./coverage/coverage-2.json && nyc merge ./coverage ./coverage/coverage.json && nyc report --reporter json-summary --reporter html --reporter text -t ./coverage --report-dir ./coverage/summary && npx @monocloud/auth-test-utils check-coverage"
|
|
64
|
-
}
|
|
63
|
+
},
|
|
64
|
+
"module": "./dist/index.mjs"
|
|
65
65
|
}
|