@atcute/oauth-browser-client 1.0.9 → 1.0.10-alpha

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/dpop.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { database } from './environment.js';
2
2
  import { extractContentType } from './utils/response.js';
3
- import { encoder, fromBase64Url, generateTimestamp, toBase64Url, toSha256 } from './utils/runtime.js';
3
+ import { encoder, fromBase64Url, generateJti, toBase64Url, toSha256 } from './utils/runtime.js';
4
4
  const ES256_ALG = { name: 'ECDSA', namedCurve: 'P-256' };
5
5
  export const createES256Key = async () => {
6
6
  const pair = await crypto.subtle.generateKey(ES256_ALG, true, ['sign', 'verify']);
@@ -16,11 +16,12 @@ export const createDPoPSignage = (issuer, dpopKey) => {
16
16
  const headerString = dpopKey.jwt;
17
17
  const keyPromise = crypto.subtle.importKey('pkcs8', fromBase64Url(dpopKey.key), ES256_ALG, true, ['sign']);
18
18
  const constructPayload = (method, url, nonce, ath) => {
19
- const now = (Date.now() / 1_000) | 0;
19
+ // Microsecond precision and somewhat monotonic, when the browser allows for it
20
+ const now = performance.timeOrigin + performance.now();
20
21
  const payload = {
21
22
  iss: issuer,
22
- iat: now,
23
- jti: generateTimestamp(),
23
+ iat: Math.floor(now / 1_000),
24
+ jti: generateJti(now),
24
25
  htm: method,
25
26
  htu: url,
26
27
  nonce: nonce,
@@ -37,6 +38,7 @@ export const createDPoPSignage = (issuer, dpopKey) => {
37
38
  };
38
39
  export const createDPoPFetch = (issuer, dpopKey, isAuthServer) => {
39
40
  const nonces = database.dpopNonces;
41
+ const pending = database.inflightDpop;
40
42
  const sign = createDPoPSignage(issuer, dpopKey);
41
43
  return async (input, init) => {
42
44
  const request = init == null && input instanceof Request ? input : new Request(input, init);
@@ -46,45 +48,66 @@ export const createDPoPFetch = (issuer, dpopKey, isAuthServer) => {
46
48
  : undefined;
47
49
  const { method, url } = request;
48
50
  const { origin } = new URL(url);
51
+ // Wait for an existing promise to resolve, before proceeding with request,
52
+ // elaborated in the next comment.
53
+ let deferred = pending.get(origin);
54
+ if (deferred) {
55
+ await deferred.promise;
56
+ deferred = undefined;
57
+ }
49
58
  let initNonce;
50
59
  try {
51
60
  initNonce = nonces.get(origin);
52
61
  }
53
62
  catch {
54
- // Ignore get errors, we will just not send a nonce
63
+ // Ignore read errors, we'll just act like we're missing a nonce.
55
64
  }
56
- const initProof = await sign(method, url, initNonce, ath);
57
- request.headers.set('dpop', initProof);
58
- const initResponse = await fetch(request);
59
- const nextNonce = initResponse.headers.get('dpop-nonce');
60
- if (!nextNonce || nextNonce === initNonce) {
61
- // No nonce was returned or it is the same as the one we sent. No need to
62
- // update the nonce store, or retry the request.
63
- return initResponse;
65
+ if (initNonce === undefined) {
66
+ // We have a missing nonce! Let's have everyone else wait so we don't end
67
+ // up with multiple failing requests.
68
+ pending.set(origin, (deferred = Promise.withResolvers()));
64
69
  }
65
- // Store the fresh nonce for future requests
66
70
  try {
67
- nonces.set(origin, nextNonce);
68
- }
69
- catch {
70
- // Ignore set errors
71
- }
72
- const shouldRetry = await isUseDpopNonceError(initResponse, isAuthServer);
73
- if (!shouldRetry) {
74
- // Not a "use_dpop_nonce" error, so there is no need to retry
75
- return initResponse;
71
+ const initProof = await sign(method, url, initNonce, ath);
72
+ request.headers.set('dpop', initProof);
73
+ const initResponse = await fetch(request);
74
+ const nextNonce = initResponse.headers.get('dpop-nonce');
75
+ if (nextNonce === null || nextNonce === initNonce) {
76
+ // No nonce was returned or it is the same as the one we sent. No need to
77
+ // update the nonce store, or retry the request.
78
+ return initResponse;
79
+ }
80
+ // Store the fresh nonce for future requests
81
+ try {
82
+ nonces.set(origin, nextNonce);
83
+ }
84
+ catch {
85
+ // Ignore write errors
86
+ }
87
+ const shouldRetry = await isUseDpopNonceError(initResponse, isAuthServer);
88
+ if (!shouldRetry) {
89
+ // Not a "use_dpop_nonce" error, so there is no need to retry
90
+ return initResponse;
91
+ }
92
+ if (input === request || init?.body instanceof ReadableStream) {
93
+ // If the input stream was already consumed, we cannot retry the request. A
94
+ // solution would be to clone() the request but that would bufferize the
95
+ // entire stream in memory which can lead to memory starvation. Instead, we
96
+ // will return the original response and let the calling code handle retries.
97
+ return initResponse;
98
+ }
99
+ const nextProof = await sign(method, url, nextNonce, ath);
100
+ const nextRequest = new Request(input, init);
101
+ nextRequest.headers.set('dpop', nextProof);
102
+ return await fetch(nextRequest);
76
103
  }
77
- // If the input stream was already consumed, we cannot retry the request. A
78
- // solution would be to clone() the request but that would bufferize the
79
- // entire stream in memory which can lead to memory starvation. Instead, we
80
- // will return the original response and let the calling code handle retries.
81
- if (input === request || init?.body instanceof ReadableStream) {
82
- return initResponse;
104
+ finally {
105
+ // Now everyone can have their turn.
106
+ if (deferred) {
107
+ pending.delete(origin);
108
+ deferred.resolve();
109
+ }
83
110
  }
84
- const nextProof = await sign(method, url, nextNonce, ath);
85
- const nextRequest = new Request(input, init);
86
- nextRequest.headers.set('dpop', nextProof);
87
- return await fetch(nextRequest);
88
111
  };
89
112
  };
90
113
  const isUseDpopNonceError = async (response, isAuthServer) => {
package/dist/dpop.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dpop.js","sourceRoot":"","sources":["../lib/dpop.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dpop.js","sourceRoot":"","sources":["../lib/dpop.ts"],"names":[],"mappings":"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"}
@@ -15,4 +15,5 @@ export declare const createOAuthDatabase: ({ name }: OAuthDatabaseOptions) => {
15
15
  verifier?: string;
16
16
  }>;
17
17
  dpopNonces: SimpleStore<string, string>;
18
+ inflightDpop: Map<string, PromiseWithResolvers<void>>;
18
19
  };
package/dist/store/db.js CHANGED
@@ -107,8 +107,9 @@ export const createOAuthDatabase = ({ name }) => {
107
107
  }
108
108
  return token.expires_at ?? null;
109
109
  }),
110
- states: createStore('states', (_item) => Date.now() + 10 * 60 * 1_000),
111
- dpopNonces: createStore('dpopNonces', (_item) => Date.now() + 10 * 60 * 1_000),
110
+ states: createStore('states', (_item) => Date.now() + 10 * 60 * 1_000), // 10 minutes
111
+ dpopNonces: createStore('dpopNonces', (_item) => Date.now() + 3 * 60 * 1_000), // 3 minutes
112
+ inflightDpop: new Map(),
112
113
  };
113
114
  };
114
115
  //# sourceMappingURL=db.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"db.js","sourceRoot":"","sources":["../../lib/store/db.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../../lib/store/db.ts"],"names":[],"mappings":"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"}
@@ -10,4 +10,4 @@ export declare const generatePKCE: () => Promise<{
10
10
  challenge: string;
11
11
  method: string;
12
12
  }>;
13
- export declare const generateTimestamp: () => string;
13
+ export declare const generateJti: (time: number) => string;
@@ -41,9 +41,9 @@ export const generatePKCE = async () => {
41
41
  method: 'S256',
42
42
  };
43
43
  };
44
- export const generateTimestamp = () => {
44
+ export const generateJti = (time) => {
45
45
  const random = crypto.getRandomValues(new BigUint64Array(1));
46
- const id = (BigInt(Math.floor(performance.timeOrigin + performance.now())) << 64n) | random[0];
46
+ const id = (BigInt(time * 1_000) << 64n) | random[0];
47
47
  return id.toString(36);
48
48
  };
49
49
  //# sourceMappingURL=runtime.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../lib/utils/runtime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../lib/utils/runtime.ts"],"names":[],"mappings":"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"}
package/lib/dpop.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { database } from './environment.js';
2
2
  import type { DPoPKey } from './types/dpop.js';
3
3
  import { extractContentType } from './utils/response.js';
4
- import { encoder, fromBase64Url, generateTimestamp, toBase64Url, toSha256 } from './utils/runtime.js';
4
+ import { encoder, fromBase64Url, generateJti, toBase64Url, toSha256 } from './utils/runtime.js';
5
5
 
6
6
  const ES256_ALG = { name: 'ECDSA', namedCurve: 'P-256' } as const;
7
7
 
@@ -28,12 +28,13 @@ export const createDPoPSignage = (issuer: string, dpopKey: DPoPKey) => {
28
28
  nonce: string | undefined,
29
29
  ath: string | undefined,
30
30
  ) => {
31
- const now = (Date.now() / 1_000) | 0;
31
+ // Microsecond precision and somewhat monotonic, when the browser allows for it
32
+ const now = performance.timeOrigin + performance.now();
32
33
 
33
34
  const payload = {
34
35
  iss: issuer,
35
- iat: now,
36
- jti: generateTimestamp(),
36
+ iat: Math.floor(now / 1_000),
37
+ jti: generateJti(now),
37
38
  htm: method,
38
39
  htu: url,
39
40
  nonce: nonce,
@@ -60,6 +61,8 @@ export const createDPoPSignage = (issuer: string, dpopKey: DPoPKey) => {
60
61
 
61
62
  export const createDPoPFetch = (issuer: string, dpopKey: DPoPKey, isAuthServer?: boolean): typeof fetch => {
62
63
  const nonces = database.dpopNonces;
64
+ const pending = database.inflightDpop;
65
+
63
66
  const sign = createDPoPSignage(issuer, dpopKey);
64
67
 
65
68
  return async (input, init) => {
@@ -73,52 +76,77 @@ export const createDPoPFetch = (issuer: string, dpopKey: DPoPKey, isAuthServer?:
73
76
  const { method, url } = request;
74
77
  const { origin } = new URL(url);
75
78
 
79
+ // Wait for an existing promise to resolve, before proceeding with request,
80
+ // elaborated in the next comment.
81
+ let deferred = pending.get(origin);
82
+ if (deferred) {
83
+ await deferred.promise;
84
+ deferred = undefined;
85
+ }
86
+
76
87
  let initNonce: string | undefined;
77
88
  try {
78
89
  initNonce = nonces.get(origin);
79
90
  } catch {
80
- // Ignore get errors, we will just not send a nonce
91
+ // Ignore read errors, we'll just act like we're missing a nonce.
81
92
  }
82
93
 
83
- const initProof = await sign(method, url, initNonce, ath);
84
- request.headers.set('dpop', initProof);
94
+ if (initNonce === undefined) {
95
+ // We have a missing nonce! Let's have everyone else wait so we don't end
96
+ // up with multiple failing requests.
85
97
 
86
- const initResponse = await fetch(request);
87
-
88
- const nextNonce = initResponse.headers.get('dpop-nonce');
89
- if (!nextNonce || nextNonce === initNonce) {
90
- // No nonce was returned or it is the same as the one we sent. No need to
91
- // update the nonce store, or retry the request.
92
- return initResponse;
98
+ pending.set(origin, (deferred = Promise.withResolvers()));
93
99
  }
94
100
 
95
- // Store the fresh nonce for future requests
96
101
  try {
97
- nonces.set(origin, nextNonce);
98
- } catch {
99
- // Ignore set errors
100
- }
102
+ const initProof = await sign(method, url, initNonce, ath);
103
+ request.headers.set('dpop', initProof);
101
104
 
102
- const shouldRetry = await isUseDpopNonceError(initResponse, isAuthServer);
103
- if (!shouldRetry) {
104
- // Not a "use_dpop_nonce" error, so there is no need to retry
105
- return initResponse;
106
- }
105
+ const initResponse = await fetch(request);
107
106
 
108
- // If the input stream was already consumed, we cannot retry the request. A
109
- // solution would be to clone() the request but that would bufferize the
110
- // entire stream in memory which can lead to memory starvation. Instead, we
111
- // will return the original response and let the calling code handle retries.
107
+ const nextNonce = initResponse.headers.get('dpop-nonce');
108
+ if (nextNonce === null || nextNonce === initNonce) {
109
+ // No nonce was returned or it is the same as the one we sent. No need to
110
+ // update the nonce store, or retry the request.
112
111
 
113
- if (input === request || init?.body instanceof ReadableStream) {
114
- return initResponse;
115
- }
112
+ return initResponse;
113
+ }
116
114
 
117
- const nextProof = await sign(method, url, nextNonce, ath);
118
- const nextRequest = new Request(input, init);
119
- nextRequest.headers.set('dpop', nextProof);
115
+ // Store the fresh nonce for future requests
116
+ try {
117
+ nonces.set(origin, nextNonce);
118
+ } catch {
119
+ // Ignore write errors
120
+ }
121
+
122
+ const shouldRetry = await isUseDpopNonceError(initResponse, isAuthServer);
123
+ if (!shouldRetry) {
124
+ // Not a "use_dpop_nonce" error, so there is no need to retry
125
+
126
+ return initResponse;
127
+ }
128
+
129
+ if (input === request || init?.body instanceof ReadableStream) {
130
+ // If the input stream was already consumed, we cannot retry the request. A
131
+ // solution would be to clone() the request but that would bufferize the
132
+ // entire stream in memory which can lead to memory starvation. Instead, we
133
+ // will return the original response and let the calling code handle retries.
120
134
 
121
- return await fetch(nextRequest);
135
+ return initResponse;
136
+ }
137
+
138
+ const nextProof = await sign(method, url, nextNonce, ath);
139
+ const nextRequest = new Request(input, init);
140
+ nextRequest.headers.set('dpop', nextProof);
141
+
142
+ return await fetch(nextRequest);
143
+ } finally {
144
+ // Now everyone can have their turn.
145
+ if (deferred) {
146
+ pending.delete(origin);
147
+ deferred.resolve();
148
+ }
149
+ }
122
150
  };
123
151
  };
124
152
 
package/lib/store/db.ts CHANGED
@@ -178,7 +178,8 @@ export const createOAuthDatabase = ({ name }: OAuthDatabaseOptions) => {
178
178
 
179
179
  return token.expires_at ?? null;
180
180
  }),
181
- states: createStore('states', (_item) => Date.now() + 10 * 60 * 1_000),
182
- dpopNonces: createStore('dpopNonces', (_item) => Date.now() + 10 * 60 * 1_000),
181
+ states: createStore('states', (_item) => Date.now() + 10 * 60 * 1_000), // 10 minutes
182
+ dpopNonces: createStore('dpopNonces', (_item) => Date.now() + 3 * 60 * 1_000), // 3 minutes
183
+ inflightDpop: new Map<string, PromiseWithResolvers<void>>(),
183
184
  };
184
185
  };
@@ -54,9 +54,9 @@ export const generatePKCE = async (): Promise<{ verifier: string; challenge: str
54
54
  };
55
55
  };
56
56
 
57
- export const generateTimestamp = (): string => {
57
+ export const generateJti = (time: number): string => {
58
58
  const random = crypto.getRandomValues(new BigUint64Array(1));
59
- const id = (BigInt(Math.floor(performance.timeOrigin + performance.now())) << 64n) | random[0];
59
+ const id = (BigInt(time * 1_000) << 64n) | random[0];
60
60
 
61
61
  return id.toString(36);
62
62
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@atcute/oauth-browser-client",
4
- "version": "1.0.9",
4
+ "version": "1.0.10-alpha",
5
5
  "description": "minimal OAuth browser client implementation for AT Protocol",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -19,10 +19,10 @@
19
19
  },
20
20
  "sideEffects": false,
21
21
  "dependencies": {
22
- "@atcute/client": "^2.0.6"
22
+ "@atcute/client": "^2.0.7"
23
23
  },
24
24
  "devDependencies": {
25
- "@types/bun": "^1.1.14"
25
+ "@types/bun": "^1.1.16"
26
26
  },
27
27
  "scripts": {
28
28
  "build": "tsc --project tsconfig.build.json",