@atproto/oauth-client-browser 0.3.41 → 0.4.0-next.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/dist/browser-oauth-client.d.ts +4 -1
- package/dist/browser-oauth-client.d.ts.map +1 -1
- package/dist/browser-oauth-client.js +24 -38
- package/dist/browser-oauth-client.js.map +1 -1
- package/dist/browser-oauth-database.d.ts +2 -2
- package/dist/browser-oauth-database.d.ts.map +1 -1
- package/dist/browser-oauth-database.js +19 -35
- package/dist/browser-oauth-database.js.map +1 -1
- package/dist/browser-runtime-implementation.d.ts +1 -1
- package/dist/browser-runtime-implementation.d.ts.map +1 -1
- package/dist/browser-runtime-implementation.js +4 -13
- package/dist/browser-runtime-implementation.js.map +1 -1
- package/dist/errors.js +2 -11
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -25
- package/dist/index.js.map +1 -1
- package/dist/indexed-db/db-index.js +8 -17
- package/dist/indexed-db/db-index.js.map +1 -1
- package/dist/indexed-db/db-object-store.js +13 -22
- package/dist/indexed-db/db-object-store.js.map +1 -1
- package/dist/indexed-db/db-transaction.d.ts +1 -1
- package/dist/indexed-db/db-transaction.d.ts.map +1 -1
- package/dist/indexed-db/db-transaction.js +13 -29
- package/dist/indexed-db/db-transaction.js.map +1 -1
- package/dist/indexed-db/db.d.ts +1 -1
- package/dist/indexed-db/db.d.ts.map +1 -1
- package/dist/indexed-db/db.js +13 -34
- package/dist/indexed-db/db.js.map +1 -1
- package/dist/indexed-db/index.js +4 -20
- package/dist/indexed-db/index.js.map +1 -1
- package/dist/indexed-db/schema.js +1 -2
- package/dist/indexed-db/util.js +2 -6
- package/dist/indexed-db/util.js.map +1 -1
- package/dist/indexed-db-store.js +5 -19
- package/dist/indexed-db-store.js.map +1 -1
- package/dist/util.js +3 -6
- package/dist/util.js.map +1 -1
- package/package.json +14 -13
|
@@ -42,7 +42,10 @@ export declare class BrowserOAuthClient extends OAuthClient implements AsyncDisp
|
|
|
42
42
|
revoke(sub: string): Promise<void>;
|
|
43
43
|
signIn(input: string, options?: AuthorizeOptions): Promise<OAuthSession>;
|
|
44
44
|
signInRedirect(input: string, options?: AuthorizeOptions): Promise<never>;
|
|
45
|
-
signInPopup(input: string, options?: Omit<AuthorizeOptions, 'state'>
|
|
45
|
+
signInPopup(input: string, options?: Omit<AuthorizeOptions, 'state'> & {
|
|
46
|
+
popupName?: string;
|
|
47
|
+
popupFeatures?: string;
|
|
48
|
+
}): Promise<OAuthSession>;
|
|
46
49
|
findRedirectUrl(): `http://[::1]${string}` | "http://127.0.0.1" | `http://127.0.0.1#${string}` | `http://127.0.0.1?${string}` | `http://127.0.0.1/${string}` | `http://127.0.0.1:${string}` | `https://${string}` | `${string}.${string}:/${string}` | undefined;
|
|
47
50
|
readCallbackParams(): URLSearchParams | null;
|
|
48
51
|
initCallback(params?: URLSearchParams | null, redirectUri?: `http://[::1]${string}` | "http://127.0.0.1" | `http://127.0.0.1#${string}` | `http://127.0.0.1?${string}` | `http://127.0.0.1/${string}` | `http://127.0.0.1:${string}` | `https://${string}` | `${string}.${string}:/${string}` | undefined): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-oauth-client.d.ts","sourceRoot":"","sources":["../src/browser-oauth-client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAEhB,KAAK,EAEL,WAAW,EACX,kBAAkB,EAClB,YAAY,EAEb,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EAIlB,MAAM,sBAAsB,CAAA;AAI7B,OAAO,EAAE,QAAQ,EAAyB,MAAM,WAAW,CAAA;AAE3D,MAAM,MAAM,yBAAyB,GAAG,QAAQ,CAC9C;IACE,cAAc,CAAC,EAAE,QAAQ,CAAC,wBAAwB,CAAC,CAAA;IACnD,YAAY,CAAC,EAAE,OAAO,CAAC,iBAAiB,EAAE,WAAW,CAAC,CAAA;IACtD,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,GAAG,IAAI,CACN,kBAAkB,EAEhB,gBAAgB,GAChB,cAAc,GACd,QAAQ,GACR,OAAO,GAEP,uBAAuB,GACvB,cAAc,GACd,YAAY,GACZ,UAAU,GACV,aAAa,GACb,gBAAgB,GAChB,kCAAkC,GAClC,gCAAgC,CACnC,CACF,CAAA;AAkCD,MAAM,MAAM,6BAA6B,GAAG,QAAQ,CAClD;IACE,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB,GAAG,IAAI,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,CACtD,CAAA;AAID,qBAAa,kBAAmB,SAAQ,WAAY,YAAW,eAAe;WAC/D,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,EAAE,6BAA6B;IAgBzE,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAwB;IAE3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsB;gBAEnC,EACV,cAEC,EAED,YAAyB,EACzB,GAAG,OAAO,EACX,EAAE,yBAAyB;IA6E5B;;;;;;;;;;;;OAYG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAElC;QAAE,OAAO,EAAE,YAAY,CAAC;QAAC,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE,GAExC;QAAE,OAAO,EAAE,YAAY,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAE/C,SAAS,CACZ;IAYK,WAAW,CAAC,OAAO,CAAC,EAAE,OAAO;;;IAiB7B,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC;IAM9D,MAAM,CAAC,GAAG,EAAE,MAAM;IAKlB,MAAM,CACV,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,YAAY,CAAC;IAQlB,cAAc,CAClB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,KAAK,CAAC;IAqBX,WAAW,CACf,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"browser-oauth-client.d.ts","sourceRoot":"","sources":["../src/browser-oauth-client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAEhB,KAAK,EAEL,WAAW,EACX,kBAAkB,EAClB,YAAY,EAEb,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EAIlB,MAAM,sBAAsB,CAAA;AAI7B,OAAO,EAAE,QAAQ,EAAyB,MAAM,WAAW,CAAA;AAE3D,MAAM,MAAM,yBAAyB,GAAG,QAAQ,CAC9C;IACE,cAAc,CAAC,EAAE,QAAQ,CAAC,wBAAwB,CAAC,CAAA;IACnD,YAAY,CAAC,EAAE,OAAO,CAAC,iBAAiB,EAAE,WAAW,CAAC,CAAA;IACtD,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,GAAG,IAAI,CACN,kBAAkB,EAEhB,gBAAgB,GAChB,cAAc,GACd,QAAQ,GACR,OAAO,GAEP,uBAAuB,GACvB,cAAc,GACd,YAAY,GACZ,UAAU,GACV,aAAa,GACb,gBAAgB,GAChB,kCAAkC,GAClC,gCAAgC,CACnC,CACF,CAAA;AAkCD,MAAM,MAAM,6BAA6B,GAAG,QAAQ,CAClD;IACE,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB,GAAG,IAAI,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,CACtD,CAAA;AAID,qBAAa,kBAAmB,SAAQ,WAAY,YAAW,eAAe;WAC/D,IAAI,CAAC,EAAE,QAAQ,EAAE,GAAG,OAAO,EAAE,EAAE,6BAA6B;IAgBzE,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAwB;IAE3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsB;gBAEnC,EACV,cAEC,EAED,YAAyB,EACzB,GAAG,OAAO,EACX,EAAE,yBAAyB;IA6E5B;;;;;;;;;;;;OAYG;IACG,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAElC;QAAE,OAAO,EAAE,YAAY,CAAC;QAAC,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE,GAExC;QAAE,OAAO,EAAE,YAAY,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAE/C,SAAS,CACZ;IAYK,WAAW,CAAC,OAAO,CAAC,EAAE,OAAO;;;IAiB7B,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC;IAM9D,MAAM,CAAC,GAAG,EAAE,MAAM;IAKlB,MAAM,CACV,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,YAAY,CAAC;IAQlB,cAAc,CAClB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,KAAK,CAAC;IAqBX,WAAW,CACf,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,GAAG;QAC1C,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,aAAa,CAAC,EAAE,MAAM,CAAA;KACvB,GACA,OAAO,CAAC,YAAY,CAAC;IAkFjB,eAAe;IAcf,kBAAkB,IAAI,eAAe,GAAG,IAAI;IActC,YAAY,CACvB,MAAM,yBAA4B,EAClC,WAAW,gPAAyB,GACnC,OAAO,CAAC;QACT,OAAO,EAAE,YAAY,CAAA;QACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KACrB,CAAC;IA0FI,CAAC,MAAM,CAAC,YAAY,CAAC;IAQ3B,OAAO;CAGR"}
|
|
@@ -1,27 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const browser_runtime_implementation_js_1 = require("./browser-runtime-implementation.js");
|
|
8
|
-
const errors_js_1 = require("./errors.js");
|
|
9
|
-
const util_js_1 = require("./util.js");
|
|
1
|
+
import { OAuthCallbackError, OAuthClient, } from '@atproto/oauth-client';
|
|
2
|
+
import { assertOAuthDiscoverableClientId, atprotoLoopbackClientMetadata, isOAuthClientIdLoopback, } from '@atproto/oauth-types';
|
|
3
|
+
import { BrowserOAuthDatabase } from './browser-oauth-database.js';
|
|
4
|
+
import { BrowserRuntimeImplementation } from './browser-runtime-implementation.js';
|
|
5
|
+
import { LoginContinuedInParentWindowError } from './errors.js';
|
|
6
|
+
import { buildLoopbackClientId } from './util.js';
|
|
10
7
|
const NAMESPACE = `@@atproto/oauth-client-browser`;
|
|
11
8
|
//- Popup channel
|
|
12
9
|
const POPUP_CHANNEL_NAME = `${NAMESPACE}(popup-channel)`;
|
|
13
10
|
const POPUP_STATE_PREFIX = `${NAMESPACE}(popup-state):`;
|
|
14
11
|
const syncChannel = new BroadcastChannel(`${NAMESPACE}(synchronization-channel:2)`);
|
|
15
|
-
const runtimeImplementation = new
|
|
16
|
-
class BrowserOAuthClient extends
|
|
12
|
+
const runtimeImplementation = new BrowserRuntimeImplementation();
|
|
13
|
+
export class BrowserOAuthClient extends OAuthClient {
|
|
17
14
|
static async load({ clientId, ...options }) {
|
|
18
15
|
if (clientId.startsWith('http:')) {
|
|
19
|
-
const clientMetadata =
|
|
16
|
+
const clientMetadata = atprotoLoopbackClientMetadata(clientId);
|
|
20
17
|
return new BrowserOAuthClient({ clientMetadata, ...options });
|
|
21
18
|
}
|
|
22
19
|
else if (clientId.startsWith('https:')) {
|
|
23
|
-
|
|
24
|
-
const clientMetadata = await
|
|
20
|
+
assertOAuthDiscoverableClientId(clientId);
|
|
21
|
+
const clientMetadata = await OAuthClient.fetchMetadata({
|
|
25
22
|
clientId,
|
|
26
23
|
...options,
|
|
27
24
|
});
|
|
@@ -31,7 +28,7 @@ class BrowserOAuthClient extends oauth_client_1.OAuthClient {
|
|
|
31
28
|
throw new TypeError(`Invalid client id: ${clientId}`);
|
|
32
29
|
}
|
|
33
30
|
}
|
|
34
|
-
constructor({ clientMetadata =
|
|
31
|
+
constructor({ clientMetadata = atprotoLoopbackClientMetadata(buildLoopbackClientId(window.location)),
|
|
35
32
|
// "fragment" is a safer default as the query params will not be sent to the server
|
|
36
33
|
responseMode = 'fragment', ...options }) {
|
|
37
34
|
if (!globalThis.crypto?.subtle) {
|
|
@@ -41,7 +38,7 @@ class BrowserOAuthClient extends oauth_client_1.OAuthClient {
|
|
|
41
38
|
// Make sure "form_post" is not used as it is not supported in the browser
|
|
42
39
|
throw new TypeError(`Invalid response mode: ${responseMode}`);
|
|
43
40
|
}
|
|
44
|
-
const database = new
|
|
41
|
+
const database = new BrowserOAuthDatabase();
|
|
45
42
|
super({
|
|
46
43
|
...options,
|
|
47
44
|
clientMetadata,
|
|
@@ -73,18 +70,7 @@ class BrowserOAuthClient extends oauth_client_1.OAuthClient {
|
|
|
73
70
|
return options.onUpdate?.call(null, sub, session);
|
|
74
71
|
},
|
|
75
72
|
});
|
|
76
|
-
|
|
77
|
-
enumerable: true,
|
|
78
|
-
configurable: true,
|
|
79
|
-
writable: true,
|
|
80
|
-
value: new AbortController()
|
|
81
|
-
});
|
|
82
|
-
Object.defineProperty(this, "database", {
|
|
83
|
-
enumerable: true,
|
|
84
|
-
configurable: true,
|
|
85
|
-
writable: true,
|
|
86
|
-
value: void 0
|
|
87
|
-
});
|
|
73
|
+
this.ac = new AbortController();
|
|
88
74
|
this.database = database;
|
|
89
75
|
const { signal } = this.ac;
|
|
90
76
|
// Trigger hooks when an event is emitted in another tab
|
|
@@ -168,9 +154,10 @@ class BrowserOAuthClient extends oauth_client_1.OAuthClient {
|
|
|
168
154
|
});
|
|
169
155
|
}
|
|
170
156
|
async signInPopup(input, options) {
|
|
157
|
+
const popupTarget = options?.popupName ?? '_blank';
|
|
171
158
|
// Open new window asap to prevent popup busting by browsers
|
|
172
|
-
const popupFeatures = 'width=600,height=600,menubar=no,toolbar=no';
|
|
173
|
-
let popup = window.open('about:blank',
|
|
159
|
+
const popupFeatures = options?.popupFeatures ?? 'width=600,height=600,menubar=no,toolbar=no';
|
|
160
|
+
let popup = window.open('about:blank', popupTarget, popupFeatures);
|
|
174
161
|
const stateKey = `${Math.random().toString(36).slice(2)}`;
|
|
175
162
|
const url = await this.authorize(input, {
|
|
176
163
|
...options,
|
|
@@ -182,7 +169,7 @@ class BrowserOAuthClient extends oauth_client_1.OAuthClient {
|
|
|
182
169
|
popup.window.location.href = url.href;
|
|
183
170
|
}
|
|
184
171
|
else {
|
|
185
|
-
popup = window.open(url.href,
|
|
172
|
+
popup = window.open(url.href, popupTarget, popupFeatures);
|
|
186
173
|
}
|
|
187
174
|
popup?.focus();
|
|
188
175
|
return new Promise((resolve, reject) => {
|
|
@@ -224,7 +211,7 @@ class BrowserOAuthClient extends oauth_client_1.OAuthClient {
|
|
|
224
211
|
}
|
|
225
212
|
else {
|
|
226
213
|
const { message, params } = result.reason;
|
|
227
|
-
reject(new
|
|
214
|
+
reject(new OAuthCallbackError(new URLSearchParams(params), message));
|
|
228
215
|
}
|
|
229
216
|
};
|
|
230
217
|
popupChannel.addEventListener('message', onMessage);
|
|
@@ -295,13 +282,13 @@ class BrowserOAuthClient extends oauth_client_1.OAuthClient {
|
|
|
295
282
|
// Revoke the credentials if the parent window was closed
|
|
296
283
|
if (!receivedByParent)
|
|
297
284
|
await result.session.signOut();
|
|
298
|
-
throw new
|
|
285
|
+
throw new LoginContinuedInParentWindowError(); // signInPopup
|
|
299
286
|
}
|
|
300
287
|
localStorage.setItem(`${NAMESPACE}(sub)`, result.session.sub);
|
|
301
288
|
return result;
|
|
302
289
|
})
|
|
303
290
|
.catch(async (err) => {
|
|
304
|
-
if (err instanceof
|
|
291
|
+
if (err instanceof OAuthCallbackError &&
|
|
305
292
|
err.state?.startsWith(POPUP_STATE_PREFIX)) {
|
|
306
293
|
await sendPopupResult({
|
|
307
294
|
key: err.state.slice(POPUP_STATE_PREFIX.length),
|
|
@@ -313,14 +300,14 @@ class BrowserOAuthClient extends oauth_client_1.OAuthClient {
|
|
|
313
300
|
},
|
|
314
301
|
},
|
|
315
302
|
});
|
|
316
|
-
throw new
|
|
303
|
+
throw new LoginContinuedInParentWindowError(); // signInPopup
|
|
317
304
|
}
|
|
318
305
|
// Most probable cause at this point is that the "state" parameter is
|
|
319
306
|
// invalid.
|
|
320
307
|
throw err;
|
|
321
308
|
})
|
|
322
309
|
.catch((err) => {
|
|
323
|
-
if (err instanceof
|
|
310
|
+
if (err instanceof LoginContinuedInParentWindowError) {
|
|
324
311
|
// parent will also try to close the popup
|
|
325
312
|
window.close();
|
|
326
313
|
}
|
|
@@ -339,7 +326,6 @@ class BrowserOAuthClient extends oauth_client_1.OAuthClient {
|
|
|
339
326
|
this[Symbol.dispose]();
|
|
340
327
|
}
|
|
341
328
|
}
|
|
342
|
-
exports.BrowserOAuthClient = BrowserOAuthClient;
|
|
343
329
|
/**
|
|
344
330
|
* Since "localhost" is often used either in IP mode or in hostname mode,
|
|
345
331
|
* and because the redirect uris must use the IP mode, we need to make sure
|
|
@@ -350,7 +336,7 @@ exports.BrowserOAuthClient = BrowserOAuthClient;
|
|
|
350
336
|
* redirect uris.
|
|
351
337
|
*/
|
|
352
338
|
function fixLocation(clientMetadata) {
|
|
353
|
-
if (!
|
|
339
|
+
if (!isOAuthClientIdLoopback(clientMetadata.client_id))
|
|
354
340
|
return;
|
|
355
341
|
if (window.location.hostname !== 'localhost')
|
|
356
342
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-oauth-client.js","sourceRoot":"","sources":["../src/browser-oauth-client.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n AuthorizeOptions,\n ClientMetadata,\n Fetch,\n OAuthCallbackError,\n OAuthClient,\n OAuthClientOptions,\n OAuthSession,\n SessionHooks,\n} from '@atproto/oauth-client'\nimport {\n OAuthClientMetadataInput,\n OAuthResponseMode,\n assertOAuthDiscoverableClientId,\n atprotoLoopbackClientMetadata,\n isOAuthClientIdLoopback,\n} from '@atproto/oauth-types'\nimport { BrowserOAuthDatabase } from './browser-oauth-database.js'\nimport { BrowserRuntimeImplementation } from './browser-runtime-implementation.js'\nimport { LoginContinuedInParentWindowError } from './errors.js'\nimport { Simplify, buildLoopbackClientId } from './util.js'\n\nexport type BrowserOAuthClientOptions = Simplify<\n {\n clientMetadata?: Readonly<OAuthClientMetadataInput>\n responseMode?: Exclude<OAuthResponseMode, 'form_post'>\n fetch?: Fetch\n } & Omit<\n OAuthClientOptions,\n // Overridden by this lib\n | 'clientMetadata'\n | 'responseMode'\n | 'keyset'\n | 'fetch'\n // Provided by this lib\n | 'runtimeImplementation'\n | 'sessionStore'\n | 'stateStore'\n | 'didCache'\n | 'handleCache'\n | 'dpopNonceCache'\n | 'authorizationServerMetadataCache'\n | 'protectedResourceMetadataCache'\n >\n>\n\nconst NAMESPACE = `@@atproto/oauth-client-browser`\n\n//- Popup channel\n\nconst POPUP_CHANNEL_NAME = `${NAMESPACE}(popup-channel)`\nconst POPUP_STATE_PREFIX = `${NAMESPACE}(popup-state):`\n\ntype PopupChannelResultData = {\n key: string\n result: PromiseRejectedResult | PromiseFulfilledResult<string>\n}\n\ntype PopupChannelAckData = {\n key: string\n ack: true\n}\n\ntype PopupChannelData = PopupChannelResultData | PopupChannelAckData\n\n//- State synchronization channel\n\ntype SyncChannelMessage = {\n [K in keyof SessionHooks & string]: {\n name: K\n args: Parameters<NonNullable<SessionHooks[K]>>\n }\n}[keyof SessionHooks]\n\nconst syncChannel = new BroadcastChannel(\n `${NAMESPACE}(synchronization-channel:2)`,\n)\n\nexport type BrowserOAuthClientLoadOptions = Simplify<\n {\n clientId: string\n signal?: AbortSignal\n } & Omit<BrowserOAuthClientOptions, 'clientMetadata'>\n>\n\nconst runtimeImplementation = new BrowserRuntimeImplementation()\n\nexport class BrowserOAuthClient extends OAuthClient implements AsyncDisposable {\n static async load({ clientId, ...options }: BrowserOAuthClientLoadOptions) {\n if (clientId.startsWith('http:')) {\n const clientMetadata = atprotoLoopbackClientMetadata(clientId)\n return new BrowserOAuthClient({ clientMetadata, ...options })\n } else if (clientId.startsWith('https:')) {\n assertOAuthDiscoverableClientId(clientId)\n const clientMetadata = await OAuthClient.fetchMetadata({\n clientId,\n ...options,\n })\n return new BrowserOAuthClient({ ...options, clientMetadata })\n } else {\n throw new TypeError(`Invalid client id: ${clientId}`)\n }\n }\n\n private readonly ac = new AbortController()\n\n private readonly database: BrowserOAuthDatabase\n\n constructor({\n clientMetadata = atprotoLoopbackClientMetadata(\n buildLoopbackClientId(window.location),\n ),\n // \"fragment\" is a safer default as the query params will not be sent to the server\n responseMode = 'fragment',\n ...options\n }: BrowserOAuthClientOptions) {\n if (!globalThis.crypto?.subtle) {\n throw new Error('WebCrypto API is required')\n }\n\n if (!['query', 'fragment'].includes(responseMode)) {\n // Make sure \"form_post\" is not used as it is not supported in the browser\n throw new TypeError(`Invalid response mode: ${responseMode}`)\n }\n\n const database = new BrowserOAuthDatabase()\n\n super({\n ...options,\n\n clientMetadata,\n responseMode,\n keyset: undefined,\n\n runtimeImplementation,\n\n sessionStore: database.getSessionStore(),\n stateStore: database.getStateStore(),\n\n didCache: database.getDidCache(),\n handleCache: database.getHandleCache(),\n dpopNonceCache: database.getDpopNonceCache(),\n authorizationServerMetadataCache:\n database.getAuthorizationServerMetadataCache(),\n protectedResourceMetadataCache:\n database.getProtectedResourceMetadataCache(),\n\n onDelete: async (sub, cause) => {\n if (localStorage.getItem(`${NAMESPACE}(sub)`) === sub) {\n localStorage.removeItem(`${NAMESPACE}(sub)`)\n }\n\n syncChannel.postMessage({\n name: 'onDelete',\n args: [sub, cause],\n } satisfies SyncChannelMessage)\n\n return options.onDelete?.call(null, sub, cause)\n },\n\n onUpdate: async (sub, session) => {\n syncChannel.postMessage({\n name: 'onUpdate',\n args: [sub, session],\n } satisfies SyncChannelMessage)\n\n return options.onUpdate?.call(null, sub, session)\n },\n })\n\n this.database = database\n\n const { signal } = this.ac\n\n // Trigger hooks when an event is emitted in another tab\n syncChannel.addEventListener(\n 'message',\n (event) => {\n if (event.source === window) return\n\n const { name, args } = event.data as SyncChannelMessage\n\n const hook = options[name]\n\n // @ts-expect-error TS has a hard time matching the args with the hook\n void hook?.(...args)\n },\n // Remove the listener when the client is disposed\n { signal },\n )\n }\n\n /**\n * This method will automatically restore any existing session, or attempt to\n * process login callback if the URL contains oauth parameters.\n *\n * Use {@link BrowserOAuthClient.initCallback} instead of this method if you\n * want to force a login callback. This can be esp. useful if you are using\n * this lib from a framework that has some kind of URL manipulation (like a\n * client side router).\n *\n * Use {@link BrowserOAuthClient.initRestore} instead of this method if you\n * want to only restore existing sessions, and bypass the automatic processing\n * of login callbacks.\n */\n async init(refresh?: boolean): Promise<\n // Session restored\n | { session: OAuthSession; state?: never }\n // Login callback processed\n | { session: OAuthSession; state: string | null }\n // No session or callback\n | undefined\n > {\n // If the URL currently contains oauth query parameters (\"state\" + \"code\" or\n // \"state\" + \"error\"), let's automatically process them.\n const params = this.readCallbackParams()\n if (params) {\n const redirectUri = this.findRedirectUrl()\n if (redirectUri) return this.initCallback(params, redirectUri)\n }\n\n return this.initRestore(refresh)\n }\n\n async initRestore(refresh?: boolean) {\n // @NOTE Fixing the location should not be needed from callback endpoints\n // since callback endpoint are required to use IP based URLs (for localhost)\n await fixLocation(this.clientMetadata)\n\n const sub = localStorage.getItem(`${NAMESPACE}(sub)`)\n if (sub) {\n try {\n const session = await this.restore(sub, refresh)\n return { session }\n } catch (err) {\n localStorage.removeItem(`${NAMESPACE}(sub)`)\n throw err\n }\n }\n }\n\n async restore(sub: string, refresh?: boolean): Promise<OAuthSession> {\n const session = await super.restore(sub, refresh)\n localStorage.setItem(`${NAMESPACE}(sub)`, session.sub)\n return session\n }\n\n async revoke(sub: string) {\n localStorage.removeItem(`${NAMESPACE}(sub)`)\n return super.revoke(sub)\n }\n\n async signIn(\n input: string,\n options?: AuthorizeOptions,\n ): Promise<OAuthSession> {\n if (options?.display === 'popup') {\n return this.signInPopup(input, options)\n } else {\n return this.signInRedirect(input, options)\n }\n }\n\n async signInRedirect(\n input: string,\n options?: AuthorizeOptions,\n ): Promise<never> {\n const url = await this.authorize(input, options)\n\n window.location.href = url.href\n\n // back-forward cache\n return new Promise<never>((resolve, reject) => {\n setTimeout(\n (err: Error) => {\n // Take the opportunity to proactively cancel the pending request\n this.abortRequest(url).then(\n () => reject(err),\n (reason) => reject(new AggregateError([err, reason])),\n )\n },\n 5e3,\n new Error('User navigated back'),\n )\n })\n }\n\n async signInPopup(\n input: string,\n options?: Omit<AuthorizeOptions, 'state'>,\n ): Promise<OAuthSession> {\n // Open new window asap to prevent popup busting by browsers\n const popupFeatures = 'width=600,height=600,menubar=no,toolbar=no'\n let popup: Window | null = window.open(\n 'about:blank',\n '_blank',\n popupFeatures,\n )\n\n const stateKey = `${Math.random().toString(36).slice(2)}`\n\n const url = await this.authorize(input, {\n ...options,\n state: `${POPUP_STATE_PREFIX}${stateKey}`,\n display: options?.display ?? 'popup',\n })\n\n options?.signal?.throwIfAborted()\n\n if (popup) {\n popup.window.location.href = url.href\n } else {\n popup = window.open(url.href, '_blank', popupFeatures)\n }\n\n popup?.focus()\n\n return new Promise<OAuthSession>((resolve, reject) => {\n const popupChannel = new BroadcastChannel(POPUP_CHANNEL_NAME)\n\n const cleanup = () => {\n clearTimeout(timeout)\n popupChannel.removeEventListener('message', onMessage)\n popupChannel.close()\n options?.signal?.removeEventListener('abort', cancel)\n popup?.close()\n }\n\n const cancel = () => {\n // @TODO Store fact that the request was cancelled, allowing any\n // callback (e.g. in the popup) to revoke the session or credentials.\n\n reject(new Error(options?.signal?.aborted ? 'Aborted' : 'Timeout'))\n cleanup()\n }\n\n options?.signal?.addEventListener('abort', cancel)\n\n const timeout = setTimeout(cancel, 5 * 60e3)\n\n const onMessage = async ({ data }: MessageEvent<PopupChannelData>) => {\n if (data.key !== stateKey) return\n if (!('result' in data)) return\n\n // Send acknowledgment to popup window\n popupChannel.postMessage({ key: stateKey, ack: true })\n\n cleanup()\n\n const { result } = data\n if (result.status === 'fulfilled') {\n const sub = result.value\n try {\n options?.signal?.throwIfAborted()\n resolve(await this.restore(sub, false))\n } catch (err) {\n reject(err)\n void this.revoke(sub)\n }\n } else {\n const { message, params } = result.reason\n reject(new OAuthCallbackError(new URLSearchParams(params), message))\n }\n }\n\n popupChannel.addEventListener('message', onMessage)\n })\n }\n\n public findRedirectUrl() {\n for (const uri of this.clientMetadata.redirect_uris) {\n const url = new URL(uri)\n if (\n location.origin === url.origin &&\n location.pathname === url.pathname\n ) {\n return uri\n }\n }\n\n return undefined\n }\n\n public readCallbackParams(): URLSearchParams | null {\n const params =\n this.responseMode === 'fragment'\n ? new URLSearchParams(location.hash.slice(1))\n : new URLSearchParams(location.search)\n\n // Only if the current URL contains a valid oauth response params\n if (!params.has('state') || !(params.has('code') || params.has('error'))) {\n return null\n }\n\n return params\n }\n\n public async initCallback(\n params = this.readCallbackParams(),\n redirectUri = this.findRedirectUrl(),\n ): Promise<{\n session: OAuthSession\n state: string | null\n }> {\n if (!params) {\n throw new TypeError('No OAuth callback parameters found in the URL')\n }\n\n // Replace the current history entry without the params (this will prevent\n // the following code to run again if the user refreshes the page)\n if (this.responseMode === 'fragment') {\n history.replaceState(null, '', location.pathname + location.search)\n } else if (this.responseMode === 'query') {\n history.replaceState(null, '', location.pathname)\n }\n\n // Utility function to send the result of the popup to the parent window\n const sendPopupResult = (message: PopupChannelResultData) => {\n const popupChannel = new BroadcastChannel(POPUP_CHANNEL_NAME)\n\n return new Promise<boolean>((resolve) => {\n const cleanup = (result: boolean) => {\n clearTimeout(timer)\n popupChannel.removeEventListener('message', onMessage)\n popupChannel.close()\n resolve(result)\n }\n\n const onMessage = ({ data }: MessageEvent<PopupChannelData>) => {\n if ('ack' in data && message.key === data.key) cleanup(true)\n }\n\n popupChannel.addEventListener('message', onMessage)\n popupChannel.postMessage(message)\n // Receiving of \"ack\" should be very fast, giving it 500 ms anyway\n const timer = setTimeout(cleanup, 500, false)\n })\n }\n\n return this.callback(params, { redirect_uri: redirectUri })\n .then(async (result) => {\n if (result.state?.startsWith(POPUP_STATE_PREFIX)) {\n const receivedByParent = await sendPopupResult({\n key: result.state.slice(POPUP_STATE_PREFIX.length),\n result: {\n status: 'fulfilled',\n value: result.session.sub,\n },\n })\n\n // Revoke the credentials if the parent window was closed\n if (!receivedByParent) await result.session.signOut()\n\n throw new LoginContinuedInParentWindowError() // signInPopup\n }\n\n localStorage.setItem(`${NAMESPACE}(sub)`, result.session.sub)\n\n return result\n })\n .catch(async (err) => {\n if (\n err instanceof OAuthCallbackError &&\n err.state?.startsWith(POPUP_STATE_PREFIX)\n ) {\n await sendPopupResult({\n key: err.state.slice(POPUP_STATE_PREFIX.length),\n result: {\n status: 'rejected',\n reason: {\n message: err.message,\n params: Array.from(err.params.entries()),\n },\n },\n })\n\n throw new LoginContinuedInParentWindowError() // signInPopup\n }\n\n // Most probable cause at this point is that the \"state\" parameter is\n // invalid.\n throw err\n })\n .catch((err) => {\n if (err instanceof LoginContinuedInParentWindowError) {\n // parent will also try to close the popup\n window.close()\n }\n\n throw err\n })\n }\n\n async [Symbol.asyncDispose]() {\n try {\n this.ac.abort()\n } finally {\n await this.database[Symbol.asyncDispose]()\n }\n }\n\n dispose() {\n this[Symbol.dispose]()\n }\n}\n\n/**\n * Since \"localhost\" is often used either in IP mode or in hostname mode,\n * and because the redirect uris must use the IP mode, we need to make sure\n * that the current location url is not using \"localhost\".\n *\n * This is required for the IndexedDB to work properly. Indeed, the IndexedDB\n * is shared by origin, so we must ensure to be on the same origin as the\n * redirect uris.\n */\nfunction fixLocation(clientMetadata: ClientMetadata) {\n if (!isOAuthClientIdLoopback(clientMetadata.client_id)) return\n if (window.location.hostname !== 'localhost') return\n\n const locationUrl = new URL(window.location.href)\n\n for (const uri of clientMetadata.redirect_uris) {\n const url = new URL(uri)\n if (\n (url.hostname === '127.0.0.1' || url.hostname === '[::1]') &&\n (!url.port || url.port === locationUrl.port) &&\n url.protocol === locationUrl.protocol &&\n url.pathname === locationUrl.pathname\n ) {\n url.port = locationUrl.port\n window.location.href = url.href\n\n // Prevent init() on the wrong origin\n throw new Error('Redirecting to loopback IP...')\n }\n }\n\n throw new Error(\n `Please use the loopback IP address instead of ${locationUrl}`,\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"browser-oauth-client.js","sourceRoot":"","sources":["../src/browser-oauth-client.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n AuthorizeOptions,\n ClientMetadata,\n Fetch,\n OAuthCallbackError,\n OAuthClient,\n OAuthClientOptions,\n OAuthSession,\n SessionHooks,\n} from '@atproto/oauth-client'\nimport {\n OAuthClientMetadataInput,\n OAuthResponseMode,\n assertOAuthDiscoverableClientId,\n atprotoLoopbackClientMetadata,\n isOAuthClientIdLoopback,\n} from '@atproto/oauth-types'\nimport { BrowserOAuthDatabase } from './browser-oauth-database.js'\nimport { BrowserRuntimeImplementation } from './browser-runtime-implementation.js'\nimport { LoginContinuedInParentWindowError } from './errors.js'\nimport { Simplify, buildLoopbackClientId } from './util.js'\n\nexport type BrowserOAuthClientOptions = Simplify<\n {\n clientMetadata?: Readonly<OAuthClientMetadataInput>\n responseMode?: Exclude<OAuthResponseMode, 'form_post'>\n fetch?: Fetch\n } & Omit<\n OAuthClientOptions,\n // Overridden by this lib\n | 'clientMetadata'\n | 'responseMode'\n | 'keyset'\n | 'fetch'\n // Provided by this lib\n | 'runtimeImplementation'\n | 'sessionStore'\n | 'stateStore'\n | 'didCache'\n | 'handleCache'\n | 'dpopNonceCache'\n | 'authorizationServerMetadataCache'\n | 'protectedResourceMetadataCache'\n >\n>\n\nconst NAMESPACE = `@@atproto/oauth-client-browser`\n\n//- Popup channel\n\nconst POPUP_CHANNEL_NAME = `${NAMESPACE}(popup-channel)`\nconst POPUP_STATE_PREFIX = `${NAMESPACE}(popup-state):`\n\ntype PopupChannelResultData = {\n key: string\n result: PromiseRejectedResult | PromiseFulfilledResult<string>\n}\n\ntype PopupChannelAckData = {\n key: string\n ack: true\n}\n\ntype PopupChannelData = PopupChannelResultData | PopupChannelAckData\n\n//- State synchronization channel\n\ntype SyncChannelMessage = {\n [K in keyof SessionHooks & string]: {\n name: K\n args: Parameters<NonNullable<SessionHooks[K]>>\n }\n}[keyof SessionHooks]\n\nconst syncChannel = new BroadcastChannel(\n `${NAMESPACE}(synchronization-channel:2)`,\n)\n\nexport type BrowserOAuthClientLoadOptions = Simplify<\n {\n clientId: string\n signal?: AbortSignal\n } & Omit<BrowserOAuthClientOptions, 'clientMetadata'>\n>\n\nconst runtimeImplementation = new BrowserRuntimeImplementation()\n\nexport class BrowserOAuthClient extends OAuthClient implements AsyncDisposable {\n static async load({ clientId, ...options }: BrowserOAuthClientLoadOptions) {\n if (clientId.startsWith('http:')) {\n const clientMetadata = atprotoLoopbackClientMetadata(clientId)\n return new BrowserOAuthClient({ clientMetadata, ...options })\n } else if (clientId.startsWith('https:')) {\n assertOAuthDiscoverableClientId(clientId)\n const clientMetadata = await OAuthClient.fetchMetadata({\n clientId,\n ...options,\n })\n return new BrowserOAuthClient({ ...options, clientMetadata })\n } else {\n throw new TypeError(`Invalid client id: ${clientId}`)\n }\n }\n\n private readonly ac = new AbortController()\n\n private readonly database: BrowserOAuthDatabase\n\n constructor({\n clientMetadata = atprotoLoopbackClientMetadata(\n buildLoopbackClientId(window.location),\n ),\n // \"fragment\" is a safer default as the query params will not be sent to the server\n responseMode = 'fragment',\n ...options\n }: BrowserOAuthClientOptions) {\n if (!globalThis.crypto?.subtle) {\n throw new Error('WebCrypto API is required')\n }\n\n if (!['query', 'fragment'].includes(responseMode)) {\n // Make sure \"form_post\" is not used as it is not supported in the browser\n throw new TypeError(`Invalid response mode: ${responseMode}`)\n }\n\n const database = new BrowserOAuthDatabase()\n\n super({\n ...options,\n\n clientMetadata,\n responseMode,\n keyset: undefined,\n\n runtimeImplementation,\n\n sessionStore: database.getSessionStore(),\n stateStore: database.getStateStore(),\n\n didCache: database.getDidCache(),\n handleCache: database.getHandleCache(),\n dpopNonceCache: database.getDpopNonceCache(),\n authorizationServerMetadataCache:\n database.getAuthorizationServerMetadataCache(),\n protectedResourceMetadataCache:\n database.getProtectedResourceMetadataCache(),\n\n onDelete: async (sub, cause) => {\n if (localStorage.getItem(`${NAMESPACE}(sub)`) === sub) {\n localStorage.removeItem(`${NAMESPACE}(sub)`)\n }\n\n syncChannel.postMessage({\n name: 'onDelete',\n args: [sub, cause],\n } satisfies SyncChannelMessage)\n\n return options.onDelete?.call(null, sub, cause)\n },\n\n onUpdate: async (sub, session) => {\n syncChannel.postMessage({\n name: 'onUpdate',\n args: [sub, session],\n } satisfies SyncChannelMessage)\n\n return options.onUpdate?.call(null, sub, session)\n },\n })\n\n this.database = database\n\n const { signal } = this.ac\n\n // Trigger hooks when an event is emitted in another tab\n syncChannel.addEventListener(\n 'message',\n (event) => {\n if (event.source === window) return\n\n const { name, args } = event.data as SyncChannelMessage\n\n const hook = options[name]\n\n // @ts-expect-error TS has a hard time matching the args with the hook\n void hook?.(...args)\n },\n // Remove the listener when the client is disposed\n { signal },\n )\n }\n\n /**\n * This method will automatically restore any existing session, or attempt to\n * process login callback if the URL contains oauth parameters.\n *\n * Use {@link BrowserOAuthClient.initCallback} instead of this method if you\n * want to force a login callback. This can be esp. useful if you are using\n * this lib from a framework that has some kind of URL manipulation (like a\n * client side router).\n *\n * Use {@link BrowserOAuthClient.initRestore} instead of this method if you\n * want to only restore existing sessions, and bypass the automatic processing\n * of login callbacks.\n */\n async init(refresh?: boolean): Promise<\n // Session restored\n | { session: OAuthSession; state?: never }\n // Login callback processed\n | { session: OAuthSession; state: string | null }\n // No session or callback\n | undefined\n > {\n // If the URL currently contains oauth query parameters (\"state\" + \"code\" or\n // \"state\" + \"error\"), let's automatically process them.\n const params = this.readCallbackParams()\n if (params) {\n const redirectUri = this.findRedirectUrl()\n if (redirectUri) return this.initCallback(params, redirectUri)\n }\n\n return this.initRestore(refresh)\n }\n\n async initRestore(refresh?: boolean) {\n // @NOTE Fixing the location should not be needed from callback endpoints\n // since callback endpoint are required to use IP based URLs (for localhost)\n await fixLocation(this.clientMetadata)\n\n const sub = localStorage.getItem(`${NAMESPACE}(sub)`)\n if (sub) {\n try {\n const session = await this.restore(sub, refresh)\n return { session }\n } catch (err) {\n localStorage.removeItem(`${NAMESPACE}(sub)`)\n throw err\n }\n }\n }\n\n async restore(sub: string, refresh?: boolean): Promise<OAuthSession> {\n const session = await super.restore(sub, refresh)\n localStorage.setItem(`${NAMESPACE}(sub)`, session.sub)\n return session\n }\n\n async revoke(sub: string) {\n localStorage.removeItem(`${NAMESPACE}(sub)`)\n return super.revoke(sub)\n }\n\n async signIn(\n input: string,\n options?: AuthorizeOptions,\n ): Promise<OAuthSession> {\n if (options?.display === 'popup') {\n return this.signInPopup(input, options)\n } else {\n return this.signInRedirect(input, options)\n }\n }\n\n async signInRedirect(\n input: string,\n options?: AuthorizeOptions,\n ): Promise<never> {\n const url = await this.authorize(input, options)\n\n window.location.href = url.href\n\n // back-forward cache\n return new Promise<never>((resolve, reject) => {\n setTimeout(\n (err: Error) => {\n // Take the opportunity to proactively cancel the pending request\n this.abortRequest(url).then(\n () => reject(err),\n (reason) => reject(new AggregateError([err, reason])),\n )\n },\n 5e3,\n new Error('User navigated back'),\n )\n })\n }\n\n async signInPopup(\n input: string,\n options?: Omit<AuthorizeOptions, 'state'> & {\n popupName?: string\n popupFeatures?: string\n },\n ): Promise<OAuthSession> {\n const popupTarget = options?.popupName ?? '_blank'\n\n // Open new window asap to prevent popup busting by browsers\n const popupFeatures =\n options?.popupFeatures ?? 'width=600,height=600,menubar=no,toolbar=no'\n let popup: Window | null = window.open(\n 'about:blank',\n popupTarget,\n popupFeatures,\n )\n\n const stateKey = `${Math.random().toString(36).slice(2)}`\n\n const url = await this.authorize(input, {\n ...options,\n state: `${POPUP_STATE_PREFIX}${stateKey}`,\n display: options?.display ?? 'popup',\n })\n\n options?.signal?.throwIfAborted()\n\n if (popup) {\n popup.window.location.href = url.href\n } else {\n popup = window.open(url.href, popupTarget, popupFeatures)\n }\n\n popup?.focus()\n\n return new Promise<OAuthSession>((resolve, reject) => {\n const popupChannel = new BroadcastChannel(POPUP_CHANNEL_NAME)\n\n const cleanup = () => {\n clearTimeout(timeout)\n popupChannel.removeEventListener('message', onMessage)\n popupChannel.close()\n options?.signal?.removeEventListener('abort', cancel)\n popup?.close()\n }\n\n const cancel = () => {\n // @TODO Store fact that the request was cancelled, allowing any\n // callback (e.g. in the popup) to revoke the session or credentials.\n\n reject(new Error(options?.signal?.aborted ? 'Aborted' : 'Timeout'))\n cleanup()\n }\n\n options?.signal?.addEventListener('abort', cancel)\n\n const timeout = setTimeout(cancel, 5 * 60e3)\n\n const onMessage = async ({ data }: MessageEvent<PopupChannelData>) => {\n if (data.key !== stateKey) return\n if (!('result' in data)) return\n\n // Send acknowledgment to popup window\n popupChannel.postMessage({ key: stateKey, ack: true })\n\n cleanup()\n\n const { result } = data\n if (result.status === 'fulfilled') {\n const sub = result.value\n try {\n options?.signal?.throwIfAborted()\n resolve(await this.restore(sub, false))\n } catch (err) {\n reject(err)\n void this.revoke(sub)\n }\n } else {\n const { message, params } = result.reason\n reject(new OAuthCallbackError(new URLSearchParams(params), message))\n }\n }\n\n popupChannel.addEventListener('message', onMessage)\n })\n }\n\n public findRedirectUrl() {\n for (const uri of this.clientMetadata.redirect_uris) {\n const url = new URL(uri)\n if (\n location.origin === url.origin &&\n location.pathname === url.pathname\n ) {\n return uri\n }\n }\n\n return undefined\n }\n\n public readCallbackParams(): URLSearchParams | null {\n const params =\n this.responseMode === 'fragment'\n ? new URLSearchParams(location.hash.slice(1))\n : new URLSearchParams(location.search)\n\n // Only if the current URL contains a valid oauth response params\n if (!params.has('state') || !(params.has('code') || params.has('error'))) {\n return null\n }\n\n return params\n }\n\n public async initCallback(\n params = this.readCallbackParams(),\n redirectUri = this.findRedirectUrl(),\n ): Promise<{\n session: OAuthSession\n state: string | null\n }> {\n if (!params) {\n throw new TypeError('No OAuth callback parameters found in the URL')\n }\n\n // Replace the current history entry without the params (this will prevent\n // the following code to run again if the user refreshes the page)\n if (this.responseMode === 'fragment') {\n history.replaceState(null, '', location.pathname + location.search)\n } else if (this.responseMode === 'query') {\n history.replaceState(null, '', location.pathname)\n }\n\n // Utility function to send the result of the popup to the parent window\n const sendPopupResult = (message: PopupChannelResultData) => {\n const popupChannel = new BroadcastChannel(POPUP_CHANNEL_NAME)\n\n return new Promise<boolean>((resolve) => {\n const cleanup = (result: boolean) => {\n clearTimeout(timer)\n popupChannel.removeEventListener('message', onMessage)\n popupChannel.close()\n resolve(result)\n }\n\n const onMessage = ({ data }: MessageEvent<PopupChannelData>) => {\n if ('ack' in data && message.key === data.key) cleanup(true)\n }\n\n popupChannel.addEventListener('message', onMessage)\n popupChannel.postMessage(message)\n // Receiving of \"ack\" should be very fast, giving it 500 ms anyway\n const timer = setTimeout(cleanup, 500, false)\n })\n }\n\n return this.callback(params, { redirect_uri: redirectUri })\n .then(async (result) => {\n if (result.state?.startsWith(POPUP_STATE_PREFIX)) {\n const receivedByParent = await sendPopupResult({\n key: result.state.slice(POPUP_STATE_PREFIX.length),\n result: {\n status: 'fulfilled',\n value: result.session.sub,\n },\n })\n\n // Revoke the credentials if the parent window was closed\n if (!receivedByParent) await result.session.signOut()\n\n throw new LoginContinuedInParentWindowError() // signInPopup\n }\n\n localStorage.setItem(`${NAMESPACE}(sub)`, result.session.sub)\n\n return result\n })\n .catch(async (err) => {\n if (\n err instanceof OAuthCallbackError &&\n err.state?.startsWith(POPUP_STATE_PREFIX)\n ) {\n await sendPopupResult({\n key: err.state.slice(POPUP_STATE_PREFIX.length),\n result: {\n status: 'rejected',\n reason: {\n message: err.message,\n params: Array.from(err.params.entries()),\n },\n },\n })\n\n throw new LoginContinuedInParentWindowError() // signInPopup\n }\n\n // Most probable cause at this point is that the \"state\" parameter is\n // invalid.\n throw err\n })\n .catch((err) => {\n if (err instanceof LoginContinuedInParentWindowError) {\n // parent will also try to close the popup\n window.close()\n }\n\n throw err\n })\n }\n\n async [Symbol.asyncDispose]() {\n try {\n this.ac.abort()\n } finally {\n await this.database[Symbol.asyncDispose]()\n }\n }\n\n dispose() {\n this[Symbol.dispose]()\n }\n}\n\n/**\n * Since \"localhost\" is often used either in IP mode or in hostname mode,\n * and because the redirect uris must use the IP mode, we need to make sure\n * that the current location url is not using \"localhost\".\n *\n * This is required for the IndexedDB to work properly. Indeed, the IndexedDB\n * is shared by origin, so we must ensure to be on the same origin as the\n * redirect uris.\n */\nfunction fixLocation(clientMetadata: ClientMetadata) {\n if (!isOAuthClientIdLoopback(clientMetadata.client_id)) return\n if (window.location.hostname !== 'localhost') return\n\n const locationUrl = new URL(window.location.href)\n\n for (const uri of clientMetadata.redirect_uris) {\n const url = new URL(uri)\n if (\n (url.hostname === '127.0.0.1' || url.hostname === '[::1]') &&\n (!url.port || url.port === locationUrl.port) &&\n url.protocol === locationUrl.protocol &&\n url.pathname === locationUrl.pathname\n ) {\n url.port = locationUrl.port\n window.location.href = url.href\n\n // Prevent init() on the wrong origin\n throw new Error('Redirecting to loopback IP...')\n }\n }\n\n throw new Error(\n `Please use the loopback IP address instead of ${locationUrl}`,\n )\n}\n"]}
|
|
@@ -23,7 +23,7 @@ export type Schema = {
|
|
|
23
23
|
dpopNonceCache: Item<string>;
|
|
24
24
|
handleCache: Item<ResolvedHandle>;
|
|
25
25
|
authorizationServerMetadataCache: Item<OAuthAuthorizationServerMetadata>;
|
|
26
|
-
protectedResourceMetadataCache: Item<OAuthProtectedResourceMetadata>;
|
|
26
|
+
protectedResourceMetadataCache: Item<OAuthProtectedResourceMetadata | null>;
|
|
27
27
|
};
|
|
28
28
|
export type DatabaseStore<V extends Value> = SimpleStore<string, V>;
|
|
29
29
|
export type BrowserOAuthDatabaseOptions = {
|
|
@@ -46,7 +46,7 @@ export declare class BrowserOAuthDatabase {
|
|
|
46
46
|
getDidCache(): DatabaseStore<DidDocument>;
|
|
47
47
|
getHandleCache(): DatabaseStore<ResolvedHandle>;
|
|
48
48
|
getAuthorizationServerMetadataCache(): undefined | DatabaseStore<OAuthAuthorizationServerMetadata>;
|
|
49
|
-
getProtectedResourceMetadataCache(): undefined | DatabaseStore<OAuthProtectedResourceMetadata>;
|
|
49
|
+
getProtectedResourceMetadataCache(): undefined | DatabaseStore<OAuthProtectedResourceMetadata | null>;
|
|
50
50
|
cleanup(): Promise<void>;
|
|
51
51
|
[Symbol.asyncDispose](): Promise<void>;
|
|
52
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-oauth-database.d.ts","sourceRoot":"","sources":["../src/browser-oauth-database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAG1C,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AAClE,OAAO,EACL,gCAAgC,EAChC,8BAA8B,EAC/B,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAC9D,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAC/D,OAAO,EAAM,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAGzD,KAAK,IAAI,CAAC,CAAC,IAAI;IACb,KAAK,EAAE,CAAC,CAAA;IACR,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,KAAK,UAAU,GAAG;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,aAAa,CAAA;CACvB,CAAA;AAgBD,MAAM,MAAM,MAAM,GAAG;IACnB,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC,GAAG;QAAE,OAAO,EAAE,UAAU,CAAA;KAAE,CAAC,CAAA;IACzE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,GAAG;QAAE,OAAO,EAAE,UAAU,CAAA;KAAE,CAAC,CAAA;IACjE,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,CAAA;IAC3B,cAAc,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IAC5B,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC,CAAA;IACjC,gCAAgC,EAAE,IAAI,CAAC,gCAAgC,CAAC,CAAA;IACxE,8BAA8B,EAAE,IAAI,CAAC,8BAA8B,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"browser-oauth-database.d.ts","sourceRoot":"","sources":["../src/browser-oauth-database.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,22 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
-
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");
|
|
6
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
-
};
|
|
8
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
-
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");
|
|
11
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
-
};
|
|
13
|
-
var _BrowserOAuthDatabase_dbPromise, _BrowserOAuthDatabase_cleanupInterval;
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.BrowserOAuthDatabase = void 0;
|
|
16
|
-
const jwk_webcrypto_1 = require("@atproto/jwk-webcrypto");
|
|
17
|
-
const index_js_1 = require("./indexed-db/index.js");
|
|
1
|
+
import { WebcryptoKey } from '@atproto/jwk-webcrypto';
|
|
2
|
+
import { DB } from './indexed-db/index.js';
|
|
18
3
|
function encodeKey(key) {
|
|
19
|
-
if (!(key instanceof
|
|
4
|
+
if (!(key instanceof WebcryptoKey) || !key.kid) {
|
|
20
5
|
throw new Error('Invalid key object');
|
|
21
6
|
}
|
|
22
7
|
return {
|
|
@@ -25,7 +10,7 @@ function encodeKey(key) {
|
|
|
25
10
|
};
|
|
26
11
|
}
|
|
27
12
|
async function decodeKey(encoded) {
|
|
28
|
-
return
|
|
13
|
+
return WebcryptoKey.fromKeypair(encoded.keyPair, encoded.keyId);
|
|
29
14
|
}
|
|
30
15
|
const STORES = [
|
|
31
16
|
'state',
|
|
@@ -36,24 +21,24 @@ const STORES = [
|
|
|
36
21
|
'authorizationServerMetadataCache',
|
|
37
22
|
'protectedResourceMetadataCache',
|
|
38
23
|
];
|
|
39
|
-
class BrowserOAuthDatabase {
|
|
24
|
+
export class BrowserOAuthDatabase {
|
|
25
|
+
#dbPromise;
|
|
26
|
+
#cleanupInterval;
|
|
40
27
|
constructor(options) {
|
|
41
|
-
|
|
42
|
-
_BrowserOAuthDatabase_cleanupInterval.set(this, void 0);
|
|
43
|
-
__classPrivateFieldSet(this, _BrowserOAuthDatabase_dbPromise, index_js_1.DB.open(options?.name ?? '@atproto-oauth-client', [
|
|
28
|
+
this.#dbPromise = DB.open(options?.name ?? '@atproto-oauth-client', [
|
|
44
29
|
(db) => {
|
|
45
30
|
for (const name of STORES) {
|
|
46
31
|
const store = db.createObjectStore(name, { autoIncrement: true });
|
|
47
32
|
store.createIndex('expiresAt', 'expiresAt', { unique: false });
|
|
48
33
|
}
|
|
49
34
|
},
|
|
50
|
-
], { durability: options?.durability ?? 'strict' })
|
|
51
|
-
|
|
35
|
+
], { durability: options?.durability ?? 'strict' });
|
|
36
|
+
this.#cleanupInterval = setInterval(() => {
|
|
52
37
|
void this.cleanup();
|
|
53
|
-
}, options?.cleanupInterval ?? 30e3)
|
|
38
|
+
}, options?.cleanupInterval ?? 30e3);
|
|
54
39
|
}
|
|
55
40
|
async run(storeName, mode, fn) {
|
|
56
|
-
const db = await
|
|
41
|
+
const db = await this.#dbPromise;
|
|
57
42
|
return await db.transaction([storeName], mode, (tx) => fn(tx.objectStore(storeName)));
|
|
58
43
|
}
|
|
59
44
|
createStore(name, { encode, decode, expiresAt, }) {
|
|
@@ -151,7 +136,7 @@ class BrowserOAuthDatabase {
|
|
|
151
136
|
});
|
|
152
137
|
}
|
|
153
138
|
async cleanup() {
|
|
154
|
-
const db = await
|
|
139
|
+
const db = await this.#dbPromise;
|
|
155
140
|
for (const name of STORES) {
|
|
156
141
|
await db.transaction([name], 'readwrite', (tx) => tx
|
|
157
142
|
.objectStore(name)
|
|
@@ -159,18 +144,17 @@ class BrowserOAuthDatabase {
|
|
|
159
144
|
.deleteAll(IDBKeyRange.upperBound(Date.now())));
|
|
160
145
|
}
|
|
161
146
|
}
|
|
162
|
-
async [
|
|
163
|
-
clearInterval(
|
|
164
|
-
|
|
165
|
-
const dbPromise =
|
|
166
|
-
|
|
147
|
+
async [Symbol.asyncDispose]() {
|
|
148
|
+
clearInterval(this.#cleanupInterval);
|
|
149
|
+
this.#cleanupInterval = undefined;
|
|
150
|
+
const dbPromise = this.#dbPromise;
|
|
151
|
+
this.#dbPromise = Promise.reject(new Error('Database has been disposed'));
|
|
167
152
|
// Avoid "unhandled promise rejection"
|
|
168
|
-
|
|
153
|
+
this.#dbPromise.catch(() => null);
|
|
169
154
|
// Spec recommends not to throw errors in dispose
|
|
170
155
|
const db = await dbPromise.catch(() => null);
|
|
171
156
|
if (db)
|
|
172
157
|
await (db[Symbol.asyncDispose] || db[Symbol.dispose]).call(db);
|
|
173
158
|
}
|
|
174
159
|
}
|
|
175
|
-
exports.BrowserOAuthDatabase = BrowserOAuthDatabase;
|
|
176
160
|
//# sourceMappingURL=browser-oauth-database.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-oauth-database.js","sourceRoot":"","sources":["../src/browser-oauth-database.ts"],"names":[],"mappings":"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","sourcesContent":["import { DidDocument } from '@atproto/did'\nimport { Key } from '@atproto/jwk'\nimport { WebcryptoKey } from '@atproto/jwk-webcrypto'\nimport { InternalStateData, Session } from '@atproto/oauth-client'\nimport {\n OAuthAuthorizationServerMetadata,\n OAuthProtectedResourceMetadata,\n} from '@atproto/oauth-types'\nimport { ResolvedHandle } from '@atproto-labs/handle-resolver'\nimport { SimpleStore, Value } from '@atproto-labs/simple-store'\nimport { DB, DBObjectStore } from './indexed-db/index.js'\nimport { TupleUnion } from './util.js'\n\ntype Item<V> = {\n value: V\n expiresAt?: string // ISO Date\n}\n\ntype EncodedKey = {\n keyId: string\n keyPair: CryptoKeyPair\n}\n\nfunction encodeKey(key: Key): EncodedKey {\n if (!(key instanceof WebcryptoKey) || !key.kid) {\n throw new Error('Invalid key object')\n }\n return {\n keyId: key.kid,\n keyPair: key.cryptoKeyPair,\n }\n}\n\nasync function decodeKey(encoded: EncodedKey): Promise<Key> {\n return WebcryptoKey.fromKeypair(encoded.keyPair, encoded.keyId)\n}\n\nexport type Schema = {\n state: Item<Omit<InternalStateData, 'dpopKey'> & { dpopKey: EncodedKey }>\n session: Item<Omit<Session, 'dpopKey'> & { dpopKey: EncodedKey }>\n didCache: Item<DidDocument>\n dpopNonceCache: Item<string>\n handleCache: Item<ResolvedHandle>\n authorizationServerMetadataCache: Item<OAuthAuthorizationServerMetadata>\n protectedResourceMetadataCache: Item<OAuthProtectedResourceMetadata>\n}\n\nexport type DatabaseStore<V extends Value> = SimpleStore<string, V>\n\nconst STORES: TupleUnion<keyof Schema> = [\n 'state',\n 'session',\n\n 'didCache',\n 'dpopNonceCache',\n 'handleCache',\n 'authorizationServerMetadataCache',\n 'protectedResourceMetadataCache',\n]\n\nexport type BrowserOAuthDatabaseOptions = {\n name?: string\n durability?: 'strict' | 'relaxed'\n cleanupInterval?: number\n}\n\nexport class BrowserOAuthDatabase {\n #dbPromise: Promise<DB<Schema>>\n #cleanupInterval?: ReturnType<typeof setInterval>\n\n constructor(options?: BrowserOAuthDatabaseOptions) {\n this.#dbPromise = DB.open<Schema>(\n options?.name ?? '@atproto-oauth-client',\n [\n (db) => {\n for (const name of STORES) {\n const store = db.createObjectStore(name, { autoIncrement: true })\n store.createIndex('expiresAt', 'expiresAt', { unique: false })\n }\n },\n ],\n { durability: options?.durability ?? 'strict' },\n )\n\n this.#cleanupInterval = setInterval(() => {\n void this.cleanup()\n }, options?.cleanupInterval ?? 30e3)\n }\n\n protected async run<N extends keyof Schema, R>(\n storeName: N,\n mode: 'readonly' | 'readwrite',\n fn: (s: DBObjectStore<Schema[N]>) => R | Promise<R>,\n ): Promise<R> {\n const db = await this.#dbPromise\n return await db.transaction([storeName], mode, (tx) =>\n fn(tx.objectStore(storeName)),\n )\n }\n\n protected createStore<N extends keyof Schema, V extends Value>(\n name: N,\n {\n encode,\n decode,\n expiresAt,\n }: {\n encode: (value: V) => Schema[N]['value'] | PromiseLike<Schema[N]['value']>\n decode: (encoded: Schema[N]['value']) => V | PromiseLike<V>\n expiresAt: (value: V) => null | Date\n },\n ): DatabaseStore<V> {\n return {\n get: async (key) => {\n // Find item in store\n const item = await this.run(name, 'readonly', (store) => store.get(key))\n\n // Not found\n if (item === undefined) return undefined\n\n // Too old (delete)\n if (item.expiresAt != null && new Date(item.expiresAt) < new Date()) {\n await this.run(name, 'readwrite', (store) => store.delete(key))\n return undefined\n }\n\n // Item found and valid. Decode\n return decode(item.value)\n },\n\n set: async (key, value) => {\n // Create encoded item record\n const item = {\n value: await encode(value),\n expiresAt: expiresAt(value)?.toISOString(),\n } as Schema[N]\n\n // Store item record\n await this.run(name, 'readwrite', (store) => store.put(item, key))\n },\n\n del: async (key) => {\n // Delete\n await this.run(name, 'readwrite', (store) => store.delete(key))\n },\n }\n }\n\n getSessionStore(): DatabaseStore<Session> {\n return this.createStore('session', {\n expiresAt: ({ tokenSet }) =>\n tokenSet.refresh_token || tokenSet.expires_at == null\n ? null\n : new Date(tokenSet.expires_at),\n encode: ({ dpopKey, ...session }) => ({\n ...session,\n dpopKey: encodeKey(dpopKey),\n }),\n decode: async ({ dpopKey, ...encoded }) => ({\n ...encoded,\n dpopKey: await decodeKey(dpopKey),\n }),\n })\n }\n\n getStateStore(): DatabaseStore<InternalStateData> {\n return this.createStore('state', {\n expiresAt: (_value) => new Date(Date.now() + 10 * 60e3),\n encode: ({ dpopKey, ...session }) => ({\n ...session,\n dpopKey: encodeKey(dpopKey),\n }),\n decode: async ({ dpopKey, ...encoded }) => ({\n ...encoded,\n dpopKey: await decodeKey(dpopKey),\n }),\n })\n }\n\n getDpopNonceCache(): DatabaseStore<string> {\n return this.createStore('dpopNonceCache', {\n expiresAt: (_value) => new Date(Date.now() + 600e3),\n encode: (value) => value,\n decode: (encoded) => encoded,\n })\n }\n\n getDidCache(): DatabaseStore<DidDocument> {\n return this.createStore('didCache', {\n expiresAt: (_value) => new Date(Date.now() + 60e3),\n encode: (value) => value,\n decode: (encoded) => encoded,\n })\n }\n\n getHandleCache(): DatabaseStore<ResolvedHandle> {\n return this.createStore('handleCache', {\n expiresAt: (_value) => new Date(Date.now() + 60e3),\n encode: (value) => value,\n decode: (encoded) => encoded,\n })\n }\n\n getAuthorizationServerMetadataCache():\n | undefined\n | DatabaseStore<OAuthAuthorizationServerMetadata> {\n return this.createStore('authorizationServerMetadataCache', {\n expiresAt: (_value) => new Date(Date.now() + 60e3),\n encode: (value) => value,\n decode: (encoded) => encoded,\n })\n }\n\n getProtectedResourceMetadataCache():\n | undefined\n | DatabaseStore<OAuthProtectedResourceMetadata> {\n return this.createStore('protectedResourceMetadataCache', {\n expiresAt: (_value) => new Date(Date.now() + 60e3),\n encode: (value) => value,\n decode: (encoded) => encoded,\n })\n }\n\n async cleanup() {\n const db = await this.#dbPromise\n\n for (const name of STORES) {\n await db.transaction([name], 'readwrite', (tx) =>\n tx\n .objectStore(name)\n .index('expiresAt')\n .deleteAll(IDBKeyRange.upperBound(Date.now())),\n )\n }\n }\n\n async [Symbol.asyncDispose]() {\n clearInterval(this.#cleanupInterval)\n this.#cleanupInterval = undefined\n\n const dbPromise = this.#dbPromise\n this.#dbPromise = Promise.reject(new Error('Database has been disposed'))\n\n // Avoid \"unhandled promise rejection\"\n this.#dbPromise.catch(() => null)\n\n // Spec recommends not to throw errors in dispose\n const db = await dbPromise.catch(() => null)\n if (db) await (db[Symbol.asyncDispose] || db[Symbol.dispose]).call(db)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"browser-oauth-database.js","sourceRoot":"","sources":["../src/browser-oauth-database.ts"],"names":[],"mappings":"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","sourcesContent":["import { DidDocument } from '@atproto/did'\nimport { Key } from '@atproto/jwk'\nimport { WebcryptoKey } from '@atproto/jwk-webcrypto'\nimport { InternalStateData, Session } from '@atproto/oauth-client'\nimport {\n OAuthAuthorizationServerMetadata,\n OAuthProtectedResourceMetadata,\n} from '@atproto/oauth-types'\nimport { ResolvedHandle } from '@atproto-labs/handle-resolver'\nimport { SimpleStore, Value } from '@atproto-labs/simple-store'\nimport { DB, DBObjectStore } from './indexed-db/index.js'\nimport { TupleUnion } from './util.js'\n\ntype Item<V> = {\n value: V\n expiresAt?: string // ISO Date\n}\n\ntype EncodedKey = {\n keyId: string\n keyPair: CryptoKeyPair\n}\n\nfunction encodeKey(key: Key): EncodedKey {\n if (!(key instanceof WebcryptoKey) || !key.kid) {\n throw new Error('Invalid key object')\n }\n return {\n keyId: key.kid,\n keyPair: key.cryptoKeyPair,\n }\n}\n\nasync function decodeKey(encoded: EncodedKey): Promise<Key> {\n return WebcryptoKey.fromKeypair(encoded.keyPair, encoded.keyId)\n}\n\nexport type Schema = {\n state: Item<Omit<InternalStateData, 'dpopKey'> & { dpopKey: EncodedKey }>\n session: Item<Omit<Session, 'dpopKey'> & { dpopKey: EncodedKey }>\n didCache: Item<DidDocument>\n dpopNonceCache: Item<string>\n handleCache: Item<ResolvedHandle>\n authorizationServerMetadataCache: Item<OAuthAuthorizationServerMetadata>\n protectedResourceMetadataCache: Item<OAuthProtectedResourceMetadata | null>\n}\n\nexport type DatabaseStore<V extends Value> = SimpleStore<string, V>\n\nconst STORES: TupleUnion<keyof Schema> = [\n 'state',\n 'session',\n\n 'didCache',\n 'dpopNonceCache',\n 'handleCache',\n 'authorizationServerMetadataCache',\n 'protectedResourceMetadataCache',\n]\n\nexport type BrowserOAuthDatabaseOptions = {\n name?: string\n durability?: 'strict' | 'relaxed'\n cleanupInterval?: number\n}\n\nexport class BrowserOAuthDatabase {\n #dbPromise: Promise<DB<Schema>>\n #cleanupInterval?: ReturnType<typeof setInterval>\n\n constructor(options?: BrowserOAuthDatabaseOptions) {\n this.#dbPromise = DB.open<Schema>(\n options?.name ?? '@atproto-oauth-client',\n [\n (db) => {\n for (const name of STORES) {\n const store = db.createObjectStore(name, { autoIncrement: true })\n store.createIndex('expiresAt', 'expiresAt', { unique: false })\n }\n },\n ],\n { durability: options?.durability ?? 'strict' },\n )\n\n this.#cleanupInterval = setInterval(() => {\n void this.cleanup()\n }, options?.cleanupInterval ?? 30e3)\n }\n\n protected async run<N extends keyof Schema, R>(\n storeName: N,\n mode: 'readonly' | 'readwrite',\n fn: (s: DBObjectStore<Schema[N]>) => R | Promise<R>,\n ): Promise<R> {\n const db = await this.#dbPromise\n return await db.transaction([storeName], mode, (tx) =>\n fn(tx.objectStore(storeName)),\n )\n }\n\n protected createStore<N extends keyof Schema, V extends Value>(\n name: N,\n {\n encode,\n decode,\n expiresAt,\n }: {\n encode: (value: V) => Schema[N]['value'] | PromiseLike<Schema[N]['value']>\n decode: (encoded: Schema[N]['value']) => V | PromiseLike<V>\n expiresAt: (value: V) => null | Date\n },\n ): DatabaseStore<V> {\n return {\n get: async (key) => {\n // Find item in store\n const item = await this.run(name, 'readonly', (store) => store.get(key))\n\n // Not found\n if (item === undefined) return undefined\n\n // Too old (delete)\n if (item.expiresAt != null && new Date(item.expiresAt) < new Date()) {\n await this.run(name, 'readwrite', (store) => store.delete(key))\n return undefined\n }\n\n // Item found and valid. Decode\n return decode(item.value)\n },\n\n set: async (key, value) => {\n // Create encoded item record\n const item = {\n value: await encode(value),\n expiresAt: expiresAt(value)?.toISOString(),\n } as Schema[N]\n\n // Store item record\n await this.run(name, 'readwrite', (store) => store.put(item, key))\n },\n\n del: async (key) => {\n // Delete\n await this.run(name, 'readwrite', (store) => store.delete(key))\n },\n }\n }\n\n getSessionStore(): DatabaseStore<Session> {\n return this.createStore('session', {\n expiresAt: ({ tokenSet }) =>\n tokenSet.refresh_token || tokenSet.expires_at == null\n ? null\n : new Date(tokenSet.expires_at),\n encode: ({ dpopKey, ...session }) => ({\n ...session,\n dpopKey: encodeKey(dpopKey),\n }),\n decode: async ({ dpopKey, ...encoded }) => ({\n ...encoded,\n dpopKey: await decodeKey(dpopKey),\n }),\n })\n }\n\n getStateStore(): DatabaseStore<InternalStateData> {\n return this.createStore('state', {\n expiresAt: (_value) => new Date(Date.now() + 10 * 60e3),\n encode: ({ dpopKey, ...session }) => ({\n ...session,\n dpopKey: encodeKey(dpopKey),\n }),\n decode: async ({ dpopKey, ...encoded }) => ({\n ...encoded,\n dpopKey: await decodeKey(dpopKey),\n }),\n })\n }\n\n getDpopNonceCache(): DatabaseStore<string> {\n return this.createStore('dpopNonceCache', {\n expiresAt: (_value) => new Date(Date.now() + 600e3),\n encode: (value) => value,\n decode: (encoded) => encoded,\n })\n }\n\n getDidCache(): DatabaseStore<DidDocument> {\n return this.createStore('didCache', {\n expiresAt: (_value) => new Date(Date.now() + 60e3),\n encode: (value) => value,\n decode: (encoded) => encoded,\n })\n }\n\n getHandleCache(): DatabaseStore<ResolvedHandle> {\n return this.createStore('handleCache', {\n expiresAt: (_value) => new Date(Date.now() + 60e3),\n encode: (value) => value,\n decode: (encoded) => encoded,\n })\n }\n\n getAuthorizationServerMetadataCache():\n | undefined\n | DatabaseStore<OAuthAuthorizationServerMetadata> {\n return this.createStore('authorizationServerMetadataCache', {\n expiresAt: (_value) => new Date(Date.now() + 60e3),\n encode: (value) => value,\n decode: (encoded) => encoded,\n })\n }\n\n getProtectedResourceMetadataCache():\n | undefined\n | DatabaseStore<OAuthProtectedResourceMetadata | null> {\n return this.createStore('protectedResourceMetadataCache', {\n expiresAt: (_value) => new Date(Date.now() + 60e3),\n encode: (value) => value,\n decode: (encoded) => encoded,\n })\n }\n\n async cleanup() {\n const db = await this.#dbPromise\n\n for (const name of STORES) {\n await db.transaction([name], 'readwrite', (tx) =>\n tx\n .objectStore(name)\n .index('expiresAt')\n .deleteAll(IDBKeyRange.upperBound(Date.now())),\n )\n }\n }\n\n async [Symbol.asyncDispose]() {\n clearInterval(this.#cleanupInterval)\n this.#cleanupInterval = undefined\n\n const dbPromise = this.#dbPromise\n this.#dbPromise = Promise.reject(new Error('Database has been disposed'))\n\n // Avoid \"unhandled promise rejection\"\n this.#dbPromise.catch(() => null)\n\n // Spec recommends not to throw errors in dispose\n const db = await dbPromise.catch(() => null)\n if (db) await (db[Symbol.asyncDispose] || db[Symbol.dispose]).call(db)\n }\n}\n"]}
|
|
@@ -4,6 +4,6 @@ export declare class BrowserRuntimeImplementation implements RuntimeImplementati
|
|
|
4
4
|
constructor();
|
|
5
5
|
createKey(algs: string[]): Promise<Key>;
|
|
6
6
|
getRandomValues(byteLength: number): Uint8Array;
|
|
7
|
-
digest(data: Uint8Array
|
|
7
|
+
digest(data: Uint8Array<ArrayBuffer>, { name }: DigestAlgorithm): Promise<Uint8Array<ArrayBuffer>>;
|
|
8
8
|
}
|
|
9
9
|
//# sourceMappingURL=browser-runtime-implementation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-runtime-implementation.d.ts","sourceRoot":"","sources":["../src/browser-runtime-implementation.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,GAAG,EACH,qBAAqB,EACrB,WAAW,EACZ,MAAM,uBAAuB,CAAA;AAW9B,qBAAa,4BAA6B,YAAW,qBAAqB;IACxE,WAAW,0BAAoB;;IAmBzB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IAI7C,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU;IAIzC,MAAM,CACV,IAAI,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"browser-runtime-implementation.d.ts","sourceRoot":"","sources":["../src/browser-runtime-implementation.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,GAAG,EACH,qBAAqB,EACrB,WAAW,EACZ,MAAM,uBAAuB,CAAA;AAW9B,qBAAa,4BAA6B,YAAW,qBAAqB;IACxE,WAAW,0BAAoB;;IAmBzB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;IAI7C,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU;IAIzC,MAAM,CACV,IAAI,EAAE,UAAU,CAAC,WAAW,CAAC,EAC7B,EAAE,IAAI,EAAE,EAAE,eAAe,GACxB,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;CAYpC"}
|
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BrowserRuntimeImplementation = void 0;
|
|
4
|
-
const jwk_webcrypto_1 = require("@atproto/jwk-webcrypto");
|
|
1
|
+
import { WebcryptoKey } from '@atproto/jwk-webcrypto';
|
|
5
2
|
/**
|
|
6
3
|
* @see {@link // https://developer.mozilla.org/en-US/docs/Web/API/LockManager/request}
|
|
7
4
|
*/
|
|
8
5
|
const nativeRequestLock = typeof navigator !== 'undefined' && navigator.locks?.request
|
|
9
6
|
? (name, fn) => navigator.locks.request(name, { mode: 'exclusive' }, async () => fn())
|
|
10
7
|
: undefined;
|
|
11
|
-
class BrowserRuntimeImplementation {
|
|
8
|
+
export class BrowserRuntimeImplementation {
|
|
12
9
|
constructor() {
|
|
13
|
-
|
|
14
|
-
enumerable: true,
|
|
15
|
-
configurable: true,
|
|
16
|
-
writable: true,
|
|
17
|
-
value: nativeRequestLock
|
|
18
|
-
});
|
|
10
|
+
this.requestLock = nativeRequestLock;
|
|
19
11
|
if (typeof crypto !== 'object' || !crypto?.subtle) {
|
|
20
12
|
throw new Error('Crypto with CryptoSubtle is required. If running in a browser, make sure the current page is loaded over HTTPS.');
|
|
21
13
|
}
|
|
@@ -27,7 +19,7 @@ class BrowserRuntimeImplementation {
|
|
|
27
19
|
}
|
|
28
20
|
}
|
|
29
21
|
async createKey(algs) {
|
|
30
|
-
return
|
|
22
|
+
return WebcryptoKey.generate(algs);
|
|
31
23
|
}
|
|
32
24
|
getRandomValues(byteLength) {
|
|
33
25
|
return crypto.getRandomValues(new Uint8Array(byteLength));
|
|
@@ -45,5 +37,4 @@ class BrowserRuntimeImplementation {
|
|
|
45
37
|
}
|
|
46
38
|
}
|
|
47
39
|
}
|
|
48
|
-
exports.BrowserRuntimeImplementation = BrowserRuntimeImplementation;
|
|
49
40
|
//# sourceMappingURL=browser-runtime-implementation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-runtime-implementation.js","sourceRoot":"","sources":["../src/browser-runtime-implementation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"browser-runtime-implementation.js","sourceRoot":"","sources":["../src/browser-runtime-implementation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAQrD;;GAEG;AACH,MAAM,iBAAiB,GACrB,OAAO,SAAS,KAAK,WAAW,IAAI,SAAS,CAAC,KAAK,EAAE,OAAO;IAC1D,CAAC,CAAC,CAAI,IAAY,EAAE,EAA4B,EAAc,EAAE,CAC5D,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,KAAK,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;IAC1E,CAAC,CAAC,SAAS,CAAA;AAEf,MAAM,OAAO,4BAA4B;IAGvC;QAFA,gBAAW,GAAG,iBAAiB,CAAA;QAG7B,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CACb,iHAAiH,CAClH,CAAA;QACH,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,wEAAwE;YACxE,yEAAyE;YACzE,qBAAqB;YACrB,OAAO,CAAC,IAAI,CACV,2EAA2E,CAC5E,CAAA;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,IAAc;QAC5B,OAAO,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IACpC,CAAC;IAED,eAAe,CAAC,UAAkB;QAChC,OAAO,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAA;IAC3D,CAAC;IAED,KAAK,CAAC,MAAM,CACV,IAA6B,EAC7B,EAAE,IAAI,EAAmB;QAEzB,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,QAAQ,CAAC;YACd,KAAK,QAAQ,CAAC;YACd,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAA;gBACpE,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAA;YAC5B,CAAC;YACD;gBACE,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,EAAE,CAAC,CAAA;QAC5D,CAAC;IACH,CAAC;CACF","sourcesContent":["import { WebcryptoKey } from '@atproto/jwk-webcrypto'\nimport {\n DigestAlgorithm,\n Key,\n RuntimeImplementation,\n RuntimeLock,\n} from '@atproto/oauth-client'\n\n/**\n * @see {@link // https://developer.mozilla.org/en-US/docs/Web/API/LockManager/request}\n */\nconst nativeRequestLock: undefined | RuntimeLock =\n typeof navigator !== 'undefined' && navigator.locks?.request\n ? <T>(name: string, fn: () => T | PromiseLike<T>): Promise<T> =>\n navigator.locks.request(name, { mode: 'exclusive' }, async () => fn())\n : undefined\n\nexport class BrowserRuntimeImplementation implements RuntimeImplementation {\n requestLock = nativeRequestLock\n\n constructor() {\n if (typeof crypto !== 'object' || !crypto?.subtle) {\n throw new Error(\n 'Crypto with CryptoSubtle is required. If running in a browser, make sure the current page is loaded over HTTPS.',\n )\n }\n\n if (!this.requestLock) {\n // There is no real need to polyfill this on older browsers. Indeed, the\n // oauth-client library will try and recover from concurrency issues when\n // refreshing tokens.\n console.warn(\n 'Locks API not available. You should consider using a more recent browser.',\n )\n }\n }\n\n async createKey(algs: string[]): Promise<Key> {\n return WebcryptoKey.generate(algs)\n }\n\n getRandomValues(byteLength: number): Uint8Array {\n return crypto.getRandomValues(new Uint8Array(byteLength))\n }\n\n async digest(\n data: Uint8Array<ArrayBuffer>,\n { name }: DigestAlgorithm,\n ): Promise<Uint8Array<ArrayBuffer>> {\n switch (name) {\n case 'sha256':\n case 'sha384':\n case 'sha512': {\n const buf = await crypto.subtle.digest(`SHA-${name.slice(3)}`, data)\n return new Uint8Array(buf)\n }\n default:\n throw new Error(`Unsupported digest algorithm: ${name}`)\n }\n }\n}\n"]}
|