UNPKG

8.16 kBJavaScriptView Raw
1var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2 if (kind === "m") throw new TypeError("Private method is not writable");
3 if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4 if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5 return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6};
7var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8 if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9 if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10 return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11};
12var _SignedCookieStore_store, _SignedCookieStore_keyring, _SignedCookieStore_key, _SignedCookieStore_verify, _SignedCookieStore_sign;
13export * from 'cookie-store-interface';
14import { bufferSourceToUint8Array } from "typed-array-utils";
15import { Base64Decoder, Base64Encoder } from "base64-encoding";
16const EXT = '.sig';
17const secretToUint8Array = (secret) => typeof secret === 'string'
18 ? new TextEncoder().encode(secret)
19 : bufferSourceToUint8Array(secret);
20/**
21 * # Signed Cookie Store
22 * A partial implementation of the [Cookie Store API](https://wicg.github.io/cookie-store)
23 * that transparently signs and verifies cookies via the Web Cryptography API.
24 *
25 * This is likely only useful in server-side implementations,
26 * but written in a platform-agnostic way.
27 */
28export class SignedCookieStore {
29 constructor(store, key, opts = {}) {
30 var _a;
31 _SignedCookieStore_store.set(this, void 0);
32 _SignedCookieStore_keyring.set(this, void 0);
33 _SignedCookieStore_key.set(this, void 0);
34 _SignedCookieStore_verify.set(this, async (cookie, sigCookie) => {
35 for (const key of __classPrivateFieldGet(this, _SignedCookieStore_keyring, "f")) {
36 const signature = new Base64Decoder().decode(sigCookie.value);
37 const message = new TextEncoder().encode([cookie.name, cookie.value].join('='));
38 const ok = await crypto.subtle.verify('HMAC', key, signature, message);
39 if (ok)
40 return true;
41 }
42 return false;
43 });
44 _SignedCookieStore_sign.set(this, async (name, value) => {
45 const message = new TextEncoder().encode([name, value].join('='));
46 const signature = await crypto.subtle.sign('HMAC', __classPrivateFieldGet(this, _SignedCookieStore_key, "f"), message);
47 return new Base64Encoder({ url: true }).encode(signature);
48 }
49 /**
50 * @throws if the signature doesn't match.
51 * @returns null when the signature cookie is missing.
52 */
53 );
54 __classPrivateFieldSet(this, _SignedCookieStore_store, store, "f");
55 __classPrivateFieldSet(this, _SignedCookieStore_key, key, "f");
56 __classPrivateFieldSet(this, _SignedCookieStore_keyring, [key, ...(_a = opts.keyring) !== null && _a !== void 0 ? _a : []], "f");
57 }
58 /**
59 * A helper function to derive a crypto key from a passphrase.
60 */
61 static async deriveCryptoKey(opts) {
62 var _a, _b, _c, _d, _e;
63 if (!opts.secret)
64 throw Error('Secret missing');
65 const passphraseKey = await (opts.format === 'jwk'
66 ? crypto.subtle.importKey('jwk', opts.secret, 'PBKDF2', false, ['deriveKey'])
67 : crypto.subtle.importKey((_a = opts.format) !== null && _a !== void 0 ? _a : 'raw', secretToUint8Array(opts.secret), 'PBKDF2', false, ['deriveKey', 'deriveBits']));
68 const key = await crypto.subtle.deriveKey({
69 name: 'PBKDF2',
70 iterations: (_b = opts.iterations) !== null && _b !== void 0 ? _b : 999,
71 hash: (_c = opts.hash) !== null && _c !== void 0 ? _c : 'SHA-256',
72 salt: opts.salt
73 ? bufferSourceToUint8Array(opts.salt)
74 : new Base64Decoder().decode('o0kcRbdpRH+H/WQzPI028A==')
75 }, passphraseKey, {
76 name: 'HMAC',
77 hash: (_d = opts.hmacHash) !== null && _d !== void 0 ? _d : 'SHA-256',
78 length: (_e = opts.length) !== null && _e !== void 0 ? _e : 128
79 }, false, ['sign', 'verify']);
80 return key;
81 }
82 async get(name) {
83 if (typeof name !== 'string')
84 throw Error('Overload not implemented.');
85 const [cookie, sigCookie] = await Promise.all([
86 __classPrivateFieldGet(this, _SignedCookieStore_store, "f").get(name),
87 __classPrivateFieldGet(this, _SignedCookieStore_store, "f").get(`${name}${EXT}`),
88 ]);
89 if (!cookie || !sigCookie)
90 return null;
91 const ok = await __classPrivateFieldGet(this, _SignedCookieStore_verify, "f").call(this, cookie, sigCookie);
92 if (!ok)
93 throw Error('No key in the keyring can verify signature!');
94 return cookie;
95 }
96 async getAll(name) {
97 if (name != null)
98 throw Error('Overload not implemented.');
99 const all = await __classPrivateFieldGet(this, _SignedCookieStore_store, "f").getAll();
100 const sigCookies = all.filter(x => x.name.endsWith(EXT));
101 const list = [];
102 for (const sigCookie of sigCookies) {
103 const name = sigCookie.name;
104 const baseCookieName = name.substring(0, name.length - EXT.length);
105 const cookie = await this.get(baseCookieName);
106 if (cookie)
107 list.push(cookie);
108 }
109 return list;
110 }
111 async set(options, value) {
112 var _a;
113 const [name, val] = typeof options === 'string'
114 ? [options, value !== null && value !== void 0 ? value : '']
115 : [options.name, (_a = options.value) !== null && _a !== void 0 ? _a : ''];
116 if (name.endsWith(EXT))
117 throw new Error('Illegal name');
118 const signature = await __classPrivateFieldGet(this, _SignedCookieStore_sign, "f").call(this, name, val);
119 const sigCookieName = `${name}${EXT}`;
120 if (typeof options === 'string') {
121 await Promise.all([
122 __classPrivateFieldGet(this, _SignedCookieStore_store, "f").set(options, val),
123 __classPrivateFieldGet(this, _SignedCookieStore_store, "f").set(sigCookieName, signature),
124 ]);
125 }
126 else {
127 // deno-lint-ignore no-unused-vars
128 const { name, value, ...init } = options;
129 await Promise.all([
130 __classPrivateFieldGet(this, _SignedCookieStore_store, "f").set(options),
131 __classPrivateFieldGet(this, _SignedCookieStore_store, "f").set({ ...init, name: sigCookieName, value: signature }),
132 ]);
133 }
134 }
135 async delete(name) {
136 if (typeof name !== 'string')
137 throw Error('Overload not implemented.');
138 await Promise.all([
139 __classPrivateFieldGet(this, _SignedCookieStore_store, "f").delete(name),
140 __classPrivateFieldGet(this, _SignedCookieStore_store, "f").delete(`${name}${EXT}`),
141 ]);
142 }
143 addEventListener(...args) {
144 return __classPrivateFieldGet(this, _SignedCookieStore_store, "f").addEventListener(...args);
145 }
146 dispatchEvent(event) {
147 return __classPrivateFieldGet(this, _SignedCookieStore_store, "f").dispatchEvent(event);
148 }
149 removeEventListener(...args) {
150 return __classPrivateFieldGet(this, _SignedCookieStore_store, "f").removeEventListener(...args);
151 }
152}
153_SignedCookieStore_store = new WeakMap(), _SignedCookieStore_keyring = new WeakMap(), _SignedCookieStore_key = new WeakMap(), _SignedCookieStore_verify = new WeakMap(), _SignedCookieStore_sign = new WeakMap();
154//# sourceMappingURL=index.js.map
\No newline at end of file