@absolutejs/auth 0.55.8 → 0.56.0
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/README.md +6 -0
- package/dist/agents/index.js +13 -3
- package/dist/agents/index.js.map +3 -3
- package/dist/compliance/cipher.d.ts +6 -0
- package/dist/index.js +63 -6
- package/dist/index.js.map +5 -5
- package/dist/oidc/keys.d.ts +12 -2
- package/dist/server.js +63 -6
- package/dist/server.js.map +5 -5
- package/dist/vault/index.d.ts +5 -0
- package/dist/vault/index.js +11184 -0
- package/dist/vault/index.js.map +112 -0
- package/package.json +8 -3
package/dist/oidc/keys.d.ts
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
type SigningKeyIdentity = {
|
|
2
2
|
kid: string;
|
|
3
|
-
privateJwk: JsonWebKey;
|
|
4
3
|
publicJwk: JsonWebKey;
|
|
5
4
|
};
|
|
5
|
+
/** ES256 signing material can remain local for development or be delegated to
|
|
6
|
+
* a non-exportable KMS/HSM adapter. External signers return the 64-byte JOSE
|
|
7
|
+
* ECDSA signature (r || s), not an ASN.1 DER envelope. */
|
|
8
|
+
export type SigningKey = SigningKeyIdentity & ({
|
|
9
|
+
privateJwk: JsonWebKey;
|
|
10
|
+
sign?: never;
|
|
11
|
+
} | {
|
|
12
|
+
privateJwk?: never;
|
|
13
|
+
sign: (input: Uint8Array) => Promise<Uint8Array>;
|
|
14
|
+
});
|
|
6
15
|
export declare const generateSigningKey: () => Promise<SigningKey>;
|
|
7
16
|
export declare const jwkThumbprint: (jwk: JsonWebKey) => Promise<string>;
|
|
8
17
|
export declare const signJwt: (payload: Record<string, unknown>, signing: SigningKey, typ?: string) => Promise<string>;
|
|
@@ -23,3 +32,4 @@ export declare const verifyJwt: (token: string, publicJwk: JsonWebKey) => Promis
|
|
|
23
32
|
[k: string]: any;
|
|
24
33
|
};
|
|
25
34
|
} | undefined>;
|
|
35
|
+
export {};
|
package/dist/server.js
CHANGED
|
@@ -3214,6 +3214,7 @@ init_crypto();
|
|
|
3214
3214
|
var ENCODER = new TextEncoder;
|
|
3215
3215
|
var ES256 = { hash: "SHA-256", name: "ECDSA" };
|
|
3216
3216
|
var KEY_PARAMS = { name: "ECDSA", namedCurve: "P-256" };
|
|
3217
|
+
var ES256_JOSE_SIGNATURE_BYTES = 64;
|
|
3217
3218
|
var toBase64Url = (bytes) => Buffer.from(bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes)).toString("base64url");
|
|
3218
3219
|
var fromBase64Url = (value) => new Uint8Array(Buffer.from(value, "base64url"));
|
|
3219
3220
|
var encodeSegment = (value) => Buffer.from(JSON.stringify(value)).toString("base64url");
|
|
@@ -3247,9 +3248,18 @@ var jwkThumbprint = async (jwk) => {
|
|
|
3247
3248
|
return toBase64Url(await crypto.subtle.digest("SHA-256", ENCODER.encode(canonical)));
|
|
3248
3249
|
};
|
|
3249
3250
|
var signJwt = async (payload, signing, typ = "JWT") => {
|
|
3250
|
-
const key = await crypto.subtle.importKey("jwk", signing.privateJwk, KEY_PARAMS, false, ["sign"]);
|
|
3251
3251
|
const input = `${encodeSegment({ alg: "ES256", kid: signing.kid, typ })}.${encodeSegment(payload)}`;
|
|
3252
|
-
const
|
|
3252
|
+
const encoded = ENCODER.encode(input);
|
|
3253
|
+
let signature;
|
|
3254
|
+
if (signing.sign !== undefined) {
|
|
3255
|
+
signature = await signing.sign(encoded);
|
|
3256
|
+
} else {
|
|
3257
|
+
const key = await crypto.subtle.importKey("jwk", signing.privateJwk, KEY_PARAMS, false, ["sign"]);
|
|
3258
|
+
signature = await crypto.subtle.sign(ES256, key, encoded);
|
|
3259
|
+
}
|
|
3260
|
+
if (signature.byteLength !== ES256_JOSE_SIGNATURE_BYTES) {
|
|
3261
|
+
throw new Error("ES256 signer must return a 64-byte JOSE signature");
|
|
3262
|
+
}
|
|
3253
3263
|
return `${input}.${toBase64Url(signature)}`;
|
|
3254
3264
|
};
|
|
3255
3265
|
var toPublicJwk = (key) => ({
|
|
@@ -12214,6 +12224,44 @@ var createSecretCipher = (keyMaterial) => ({
|
|
|
12214
12224
|
decrypt: (ciphertext) => decryptSecret(ciphertext, keyMaterial),
|
|
12215
12225
|
encrypt: (plaintext) => encryptSecret(plaintext, keyMaterial)
|
|
12216
12226
|
});
|
|
12227
|
+
var VERSIONED_CIPHERTEXT_PREFIX = "absolute-vault";
|
|
12228
|
+
var VERSIONED_CIPHERTEXT_SEGMENTS = 3;
|
|
12229
|
+
var parseVersionedCiphertext = (value) => {
|
|
12230
|
+
const [prefix, encodedVersion, ciphertext] = value.split(":", VERSIONED_CIPHERTEXT_SEGMENTS);
|
|
12231
|
+
if (prefix !== VERSIONED_CIPHERTEXT_PREFIX || !encodedVersion || !ciphertext)
|
|
12232
|
+
return null;
|
|
12233
|
+
const version = Number(encodedVersion);
|
|
12234
|
+
if (!Number.isSafeInteger(version) || version < 1)
|
|
12235
|
+
return null;
|
|
12236
|
+
return { ciphertext, version };
|
|
12237
|
+
};
|
|
12238
|
+
var createVersionedSecretCipher = ({
|
|
12239
|
+
currentVersion,
|
|
12240
|
+
keys,
|
|
12241
|
+
legacyKey
|
|
12242
|
+
}) => {
|
|
12243
|
+
if (!Number.isSafeInteger(currentVersion) || currentVersion < 1)
|
|
12244
|
+
throw new Error("Vault key version must be a positive integer");
|
|
12245
|
+
const currentKey = keys[currentVersion];
|
|
12246
|
+
if (!currentKey)
|
|
12247
|
+
throw new Error(`Vault key version ${currentVersion} is unavailable`);
|
|
12248
|
+
return {
|
|
12249
|
+
decrypt: async (value) => {
|
|
12250
|
+
const envelope = parseVersionedCiphertext(value);
|
|
12251
|
+
if (!envelope) {
|
|
12252
|
+
if (!legacyKey)
|
|
12253
|
+
throw new Error("Legacy vault ciphertext key is unavailable");
|
|
12254
|
+
return decryptSecret(value, legacyKey);
|
|
12255
|
+
}
|
|
12256
|
+
const key = keys[envelope.version];
|
|
12257
|
+
if (!key)
|
|
12258
|
+
throw new Error(`Vault key version ${envelope.version} is unavailable`);
|
|
12259
|
+
return decryptSecret(envelope.ciphertext, key);
|
|
12260
|
+
},
|
|
12261
|
+
encrypt: async (plaintext) => `${VERSIONED_CIPHERTEXT_PREFIX}:${currentVersion}:${await encryptSecret(plaintext, currentKey)}`,
|
|
12262
|
+
needsReencryption: (value) => parseVersionedCiphertext(value)?.version !== currentVersion
|
|
12263
|
+
};
|
|
12264
|
+
};
|
|
12217
12265
|
|
|
12218
12266
|
// src/vault/config.ts
|
|
12219
12267
|
var createVault = ({
|
|
@@ -12225,7 +12273,15 @@ var createVault = ({
|
|
|
12225
12273
|
const entry = await store.getEntry(ownerId, name);
|
|
12226
12274
|
if (entry === undefined)
|
|
12227
12275
|
return;
|
|
12228
|
-
|
|
12276
|
+
const plaintext = await cipher.decrypt(entry.encryptedValue);
|
|
12277
|
+
if (cipher.needsReencryption?.(entry.encryptedValue)) {
|
|
12278
|
+
await store.saveEntry({
|
|
12279
|
+
...entry,
|
|
12280
|
+
encryptedValue: await cipher.encrypt(plaintext),
|
|
12281
|
+
updatedAt: Date.now()
|
|
12282
|
+
});
|
|
12283
|
+
}
|
|
12284
|
+
return plaintext;
|
|
12229
12285
|
},
|
|
12230
12286
|
list: async (ownerId) => (await store.listEntries(ownerId)).map((entry) => entry.name),
|
|
12231
12287
|
put: async (ownerId, name, value) => {
|
|
@@ -12249,11 +12305,12 @@ var rotateVaultKey = async ({
|
|
|
12249
12305
|
const newCipher = createSecretCipher(newKey);
|
|
12250
12306
|
const entries = await store.listAllEntries();
|
|
12251
12307
|
const now = Date.now();
|
|
12252
|
-
|
|
12308
|
+
await entries.reduce(async (pending, entry) => {
|
|
12309
|
+
await pending;
|
|
12253
12310
|
const plaintext = await oldCipher.decrypt(entry.encryptedValue);
|
|
12254
12311
|
const encryptedValue = await newCipher.encrypt(plaintext);
|
|
12255
12312
|
await store.saveEntry({ ...entry, encryptedValue, updatedAt: now });
|
|
12256
|
-
}
|
|
12313
|
+
}, Promise.resolve());
|
|
12257
12314
|
return { rotated: entries.length };
|
|
12258
12315
|
};
|
|
12259
12316
|
// src/vault/inMemoryVaultStore.ts
|
|
@@ -29614,5 +29671,5 @@ export {
|
|
|
29614
29671
|
auth2 as auth
|
|
29615
29672
|
};
|
|
29616
29673
|
|
|
29617
|
-
//# debugId=
|
|
29674
|
+
//# debugId=15A591E91DD3DB9A64756E2164756E21
|
|
29618
29675
|
//# sourceMappingURL=server.js.map
|